- 提高应用启动速度splash页面瞬间响应
App启动时闪屏页的白屏或者黑屏现象(取决于你所选取的Theme),无论怎么优化Application和启动页的onCreate都无法消除,毕竟解析界面是需要一定时间的,此时可以通过自定义启动页面的windowBackground来解决这个问题。代码如下:
<style name="AppSplash" parent="android:Theme">
<item name="android:windowBackground">启动页的背景图片</item>
<item name="android:windowNoTitle">true</item>
</style>
TextView实现跑马灯效果
普通textView需要设置四个属性- android:singleLine=”true”
- android:ellipsize=”marquee”
- android:focusable=”true”
- android:focusableInTouchMode=”true”
<TextView android:layout_width="300dp" android:layout_height="wrap_content" android:singleLine="true" android:ellipsize="marquee" android:textSize="24sp" android:focusable="true" android:focusableInTouchMode="true" android:text="这些条件必备的情况下,控件必须获得焦点才能实现跑马灯效果" />
ListView中的textView
存在焦点的问题 所以需要额外在布局中添加一行代码
android:marqueeRepeatLimit="marquee_forever"
并在adapter中初始化view的时候添加代码
textView.setSelected(true);
TaskAffinity singleTask allowTaskReparenting组合使用 这几个属性在manifest中指定
TaskAffinity 用于指定activity所运行的栈的名字 默认为包名
allowTaskReparenting 允许activity的task重新指定
TaskAffinity和singleTask配合使用时 该activity会运行在TaskAffinity指定的栈内
TaskAffinity和allowTaskReparenting配合使用时 情况比较复杂 举例说明例如应用B中的一个activity指定了上述两个属性 此时A启动了应用B的该activity 此时该activity运行在应用A的栈内
此时启动应用B 系统发现该activity应该运行的栈已经存在了 那么此时就会将该activity从应用A的栈中转移到应用B的栈中
此时你会发现一个神奇的现象 就是应用B并没有显示他的MAinActivity 而是显示的是我们刚才在应用A中启动的activityActivity中的moveTaskToBack(boolean nonRoot)
- 正常状态下我们按下返回键 会将当前Activity销毁
而如果我们不想销毁这个activity 而是想保持其状态的话 可以调用上述方法 - moveTadkToBack() 在activity中调用该方法可以将activity退到后台 注意并不是finish 而是类似于最小化的状态 此时我们的activity只会执行onPause onStop方法 而不会执行onDestory方法 由于是后台状态 只要我们的进程不被杀死 下次这个activity启动的时候不会执行onCreate方法 只有第一次启动的时候才会调用onCreate方法
- moveTaskToBack()方法中的参数指的是:
nonRoot=true –> 仅当activity为task中的根activity时有效
nonRoot=false –>任何时候都有效
- 正常状态下我们按下返回键 会将当前Activity销毁
view.performClick();
调用该方法 如果这个view设置了点击事件的话 相当于调用了view的点击事件fragment.setUserVisibleHint(boolean)
一般该方法配合transaction.hide()方法同时使用 用于fragment的lazyload 该方法是通知系统该fragment的UI是否是可见的
参考资料—–Fragment的setUserVisibleHint方法实现懒加载
layoutAnimation
LayoutAnimation作用于ViewGroup,为ViewGroup指定一个动画,当他的子元素出场的时候都会附带该动画效果,常用于ListView中。使用方法如下:定义LayoutAnimation
// res/anim/anim_layout.xml <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:delay="0.5" android:animationOrder="normal" android:animation="@anim/anim_item"/>
上述属性的含义如下:
android:delay
表示子元素开始动画的延迟时间,假设我们在动画中定义总时间为100ms,那么0.5表示第一个子元素延迟50ms进入,第二个延迟100ms进入,以此类推。
android: animationOrder
表示子元素动画的顺序,有三个选项:normal、reverse、random,normal表示按顺序进入,reverse表示倒叙进入,random表示随即进入。
android:animation
为子元素指定入场动画。
定义子元素的动画
// res/anim/anim_item.xml <?xml version="1.0" encoding="utf-8"?> <set xmlms:android="http://schemas.android.com/apk/res/android" android:duration="300" android:interpolator="@android:anim/accelerate_interpolator" android:shareInterpolator="true"> <alpha android:fromAlpha="0.0" android:toAlpha="1.0"/> <translate android:fromXDelta="500" android:toXDelta="0"/> </set>
为ViewGroup指定android:layoutAnimation属性:
在xml布局中:androidlayoutAnimation=”@anim/anim_layout”
或者在代码中:ListView listView = findViewById(R.id.listview); Animation animation = AnimationUtils.loadAnimation(this,R.anim.anim_layout); LayoutAnimationController controller = new LayoutAnimationController(animation); controller.setDelay(0.5f); controller.setOrder(LayoutAnimationController.ORDER_NOMAL); listView.setLayoutAnimation(controller);
使用View动画中需要注意的问题,View动画是对View的影像做出的改变,因此有时候会出现动画完成之后View无法隐藏的现象,即setVisibility(View.GONE)失效了,这个时候只需要调用view.clearAnimation()清除View动画,即可解决这个问题。
从3.0开始,属性动画的单击事件触发位置为移动之后的位置,但是View动画的触发位置仍然在原位置,所以,应当尽量使用属性动画来替代View动画。
recycleView.notify方法
notifyItemChanged(int position),position数据发生了改变,那调用这个方法,就会回调对应position的onBindViewHolder()方法了,当然,因为ViewHolder是复用的,所以如果position在当前屏幕以外,也就不会回调了,因为没有意义,下次position滚动会当前屏幕以内的时候同样会调用onBindViewHolder()方法刷新数据了。其他的方法也是同样的道理。
public final void notifyItemRangeChanged(int positionStart, int itemCount),顾名思义,可以刷新从positionStart开始itemCount数量的item了(这里的刷新指回调onBindViewHolder()方法)。
public final void notifyItemInserted(int position),这个方法是在第position位置被插入了一条数据的时候可以使用这个方法刷新,注意这个方法调用后会有插入的动画,这个动画可以使用默认的,也可以自己定义。
public final void notifyItemMoved(int fromPosition, int toPosition),这个方法是从fromPosition移动到toPosition为止的时候可以使用这个方法刷新
public final void notifyItemRangeInserted(int positionStart, int itemCount),显然是批量添加。
public final void notifyItemRemoved(int position),第position个被删除的时候刷新,同样会有动画。
public final void notifyItemRangeRemoved(int positionStart, int itemCount),批量删除。
在viewgroup中对一个view进行重复的添加和移除的时候,移除view时需使用如下代码:
new Handler().post(new Runnable() { public void run() { parent.removeView(decoration); } });
否则会报错,
java.lang.NullPointerException: Attempt to read from field ‘int android.view.View.mViewFlags’ on a null object reference
so 包问题
java.lang.UnsatisfiedLinkError dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/ * /base.apk”],nativeLibraryDirectories=[/data/app/ * /lib/arm, /vendor/lib, /system/lib]]] couldn’t find ” *.so”
发生问题的手机对应的平台目录下边没有放入so包 导致系统不能正确加载dlopen failed: “/data/app/ * -1/lib/arm/ *.so” has unexpected e_machine: 3
发生问题的手机对应的平台目录下边so包放置错误,例如x86目录下放置的是arm平台的包,当各平台so包文件名一致时需要多注意
recycleview中item设置matchparent无效
解决方案:在adapter中修改:
View view = View.inflate(parent.getContext(), R.layout.item_fra_main2, null);
View view = mInflater.from(mContext).inflate(R.layout.item_fra_main2, parent, false);
初始化view 的时候从第一种改为第二种方式即可。此时item的属性会跟着parent的属性走。模拟虚拟按键
4.0之前private void sendKeyEvent(int keyCode) { int eventCode = keyCode; long now = SystemClock.uptimeMillis(); try { KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, eventCode, 0); KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, eventCode, 0); (IWindowManager.Stub .asInterface(ServiceManager.getService("window"))) .injectInputEventNoWait(down); (IWindowManager.Stub .asInterface(ServiceManager.getService("window"))) .injectInputEventNoWait(up); } catch (RemoteException e) { Log.i(TAG, "DeadOjbectException"); } }
4.0之后,在子线程中执行如下代码,可以模拟返回键
public static void simulateKey(final int KeyCode) { new Thread () { public void run () { try { Instrumentation inst=new Instrumentation(); inst.sendKeyDownUpSync(KeyCode); } catch(Exception e) { Log.e("Exception when sendKeyDownUpSync", e.toString()); } } }.start(); }
代码对文件进行重命名
File from =new File(path) ;
File to=new File(path) ;
from.renameTo(to) ; 重命名sd卡文件的
//to为重命名之后的文件
return to;substring(int beginIndex, int endIndex)
使用该函数截取字符串的时候,如果需要截到字符串的最后一位,那么第二个参数填写的是string.length(),而不是string.length()-1,因为查看函数源码会发现,函数最终调用的是native方法fastSubstring,而第二个参数的作用是用来和第一个参数相减使用的。
Mac配置adb环境变量
- 启动终端Terminal
- 输入 cd ~
- 输入 echo $HOME
- 创建.bash_profile, 可使用 vi .bash_profile (如果已存在,则自动编辑;如不存在,则自动新建)
- 输入 export PATH=${PATH}: <1> : <2>(其中红字为必须输入,<1> <2>之间用分号相隔,为Android SDK下的 tools 目录路径,为Android SDK下的 platform-tools 目录路径<使用pwd可以直接显示路径全称>)
- 保存该文件。
- 输入 source .bash_profile 更新刚配置的环境变量。
Android studio Wifi调试小工具
源码地址:https://github.com/pedrovgs/AndroidWiFiADB
在Android studio中打开Preferences/Settings->Plugins->Browse Repositories
搜索Android WiFi ADB 安装重启即可 首次连接需要先通过数据线连接 并且电脑和手机处于同一无线网络中 点击插件小图标连接 成功之后即可进行无线真机调试了忽略方法数限制
在build.gradle中添加如下代码,设置dexOptions的,不做方法数限制的检查,这样做的缺点是apk无法再低版本的设备上运行。
git初次提交报错,push rejected,pull也失败
Git Pull Failed,fatal: refusing to merge unrelated histories
可以尝试在version control中右键rebase on 进行合并。
某些手机上边直接使用getDrawable会报错NoSuchMethod 使用getResources.getDrawable()可以解决该问题
重启应用
private void restartApplication() {
final Intent intent =
getPackageManager().getLaunchIntentForPackage(getPackageName());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
- 使用adb命令对设备进行截图操作 并回传到电脑上
adb shell /system/bin/screencap -p /sdcard/screenshot.png
adb pull /sdcard/screenshot.png /Users/macmini/Downloads/screenshot.png
- 权限
void checkPermissions() {
if (ContextCompat.checkSelfPermission(this,Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED) {
if (!ActivityCompat.shouldShowRequestPermissionRationale
(this,Manifest.permission.READ_CONTACTS)) {
//第一次全新进入时,shouldShowRequestPermissionRationale方法将返回false,这里将会执行。
//请求权限时如果点了拒绝但是没勾选不再提醒,shouldShowRequestPermissionRationale方法将返回true,这里将不执行。
//点了拒绝且勾选了不再提醒,再次进入时,shouldShowRequestPermissionRationale方法也将返回false,并且权限请求将无任何响应,然后可以在下面方法中做些处理,提示用户打开权限。
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CONTACTS},1);
} else {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CONTACTS},1);
}
}
}
- Intent清空堆栈内所有的activity
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
- activity不在堆栈中保留历史记录
在activity的xml中设置 android:noHistory="true" 当该activity不可见时 自动销毁 并且不在堆栈中保留历史记录 也就是从下一个activity不能返回该activity