setBackgroundResource(0)——可以移除View的背景色
Resources.getSystem().getDisplayMetrics().density——可以不用Context也能获取屏幕密度
通过重载ViewGroup的dispatchDraw可以实现一个简单的蒙版效果。
例如下拉刷新时,可以在contentView上加一层遮罩。
canvas.drawRect(0, mContentView.getTranslationY(), getWidth(), getHeight(), mMaskPaint);
new出来的View可以用View.generateViewId()(API 17以上可用)生成id,系统保证唯一
使用GridView时android:padding和 android:clipToPadding="false"配合使用效果更好
SparseArray——目前有很多地方从性能优化方说使用SparseArray来替换hashMap,来节省内存,提高性能。
静态变量不要直接或者间接引用Activity、Service等。这会使用Activity以及它所引用的所有对象无法释放,然后,用户操作时间一长,内存就会狂升。
SharedPreferences.Editor.apply——这个方法只在API Level>=9才会支持,需要做兼容。不过,最新的 support v4 包已经为我们做好了处理,使用
SharedPreferencesCompat.EditorCompat.getInstance().apply(editor)
apply方法是将share的修改提交到内存而后异步写入磁盘,但是commit是直接写入磁盘,这就造成两者性能上的差异,犹如apply不直接写入磁盘而share本身是单例创建,apply方法会覆写之前内存中的值,异步写入磁盘的值只是最后的值,而commit每次都要写入磁盘,而磁盘的写入相对来说是很低效的,所以apply方法在频繁调用时要比commit效率高很多。
apply虽然高效但是commit也有着自己的优势那就是它可以返回每次操作的成功与否的返回值,根据它我们就可以在操作失败时做一些补救操作。
综上,studio提示我们使用apply是在效率上的优化考虑,但是如果你很重视share是否成功操作,并希望在失败时做相应的提示或者补救commit还是更好的选择。
PackageManager.getInstalledPackages——这个方法经常使用,你可能不知道,当获取的结果数量比较多的时候,在某些机型上面调用它花费的时间可能秒级的,所以尽量在子线程中使用。另外,如果结果太多,超过系统设置的Binder数据最大传输量的上限,则会发生TransactionException,如果你使用这个方法获取机器上的己安装应用列表,最好做一下预防。
如果使用Context.startActivity启动外部应用,最好做一下异常预防,因为寻找不到对应的应用时,会抛出异常。如果你要打开的是应用内的Activity,不妨使用显式Intent,这样能提高系统搜索目标Activity的效率。
Application的生命周期就是进程的生命周期。只有进程被干掉时,Application才会销毁。哪怕是没有Activity、Service在运行,Application也会存在。所以,为了减少内存压力,尽量不要在Application里面引用大对象、Context等。
设置全屏方法——通过代码设置或者通过manifest文件设置。用代码设置全屏时,app在我们应用运行后,可能会看到短暂的状态栏,然后才全屏,而第二种方法是不会有这种情况的,所以推荐第二种。
//方法1:
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN,WindowManager.LayoutParams. FLAG_FULLSCREEN);
//必须在setContentView()之前调用
setContentView(R.layout.main);
//方法2:
viewpager.setCurrentItem——一定要在 setAdapter方法之后调用才会有效果
判断手机是不是飞行模式
boolean isEnabled = Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) == 1;
TabLayout 修改字体的方法——官方的 TabLayout 没有提供修改TextView size的方法,可以新建一个 style
再在 TabLayout 的布局文件里设置
app:tabTextAppearance="@style/CustomTabLayoutTextAppearance"
遍历HashMap的最佳方法
public static void printMap(Map mp) {
for (Map.Entry m : mp.entrySet()) {
System.out.println(m.getKey() + ":" + m.getValue());
}
}
使用Java在一个区间内产生随机整数
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
如果子类实现Serializable接口而父类未实现时,父类不会被序列化,但此时父类必须有个无参构造方法,否则会抛InvalidClassException异常。
transient关键字修饰变量可以限制序列化。
类继承之间的调用顺序 父类static成员 -> 子类static成员 -> 父类普通成员初始化和初始化块 -> 父类构造方法 -> 子类普通成员初始化和初始化块 -> 子类构造方法
后台service经常因为重启之类的出现onStartCommand()中的Intent传递的参数为null, 通过在onStartCommand()中的返回值改成return super.onStartCommand(intent, Service.START_REDELIVER_INTENT, startId); 可以解决问题。
在多进程之间不要用SharedPreferences共享数据,虽然可以(MODE_MULTI_PROCESS),但极不稳定
有些时候不能使用Application的Context,不然会报错(比如启动Activity,显示Dialog等)
备注:大家注意看到有一些NO上添加了一些数字,其实这些从能力上来说是YES,但是为什么说是NO呢?下面一个一个解释:
1. 数字1:启动Activity在这些类中是可以的,但是需要创建一个新的task,一般情况不推荐;
2. 数字2:在这些类中去layout inflate是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用;
3. 数字3:在Receiver为null时允许,在4.2或以上的版本中,用于获取黏性广播的当前值。(可以无视);
4. ContentProvider、BroadcastReceiver之所以在上述表格中,是因为在其内部方法中都有一个context用于使用。
谨慎使用Android的透明主题,透明主题会导致很多问题,比如:如果新的Activity采用了透明主题,那么当前Activity的onStop方法不会被调用;在设置为透明主题的Activity界面按Home键时,可能会导致刷屏不干净的问题;进入主题为透明主题的界面会有明显的延时感。
不要在非UI线程中初始化ViewStub,否则会返回null
尽量不要通过Application缓存数据,这不稳定
android listview中的消息被软键盘遮挡了,在设置listview的时候加上android:transcriptMode="normal"就好了
TextUtils 是一个非常好用的工具类,把 List 转成字符串,逗号分隔,逗号分隔的 String 字符串,切割成 List ,分别可以用 TextUtils 的 join 和 split 方法。如果要对 List 去重,则可以用 Collection 的 frequency 方法。
在activity中调用 moveTaskToBack (boolean nonRoot)方法即可将activity 退到后台,注意不是finish()退出。
activity中的runOnUiThread(Runnable action)方法可以直接回到主线程
listview有个footerDividersEnabled和headerDividersEnabled方法可以设置listview的顶部和底部divide,但是必须保证你设置了headview和footview才会有效果
Throwable类中的getStackTrace()方法,根据这个方法可以得到函数的逐层调用地址,其返回值为StackTraceElement[];
StackTraceElement类,其中四个方法getClassName(),getFileName(),getLineNumber(),getMethodName()在调试程序打印Log时非常有用;
UncaughtExceptionHandler接口,再好的代码异常难免,利用此接口可以对未捕获的异常善后
view的isShown方法,只有当view本身以及它的所有祖先们都是visible时,isShown()才返回TRUE。而平常我们调用if(view.getVisibility() == View.VISIBLE)只是对view本身而不对祖先的可见性进行判断。
Arrays类中的一系列关于数组操作的工具方法:binarySearch(),asList(),equals(),sort(),toString(),copyOfRange()等;
Collections类中的一系列关于集合操作的工具方法:sort(),reverse()等;
TextView类中的append(CharSequence)方法,添加文本。一些特殊文本直接用+连接会变成String;
System类中的arraycopy(src, srcPos, dest, destPos, length)方法,用来copy数组;
Fragment类中的onHiddenChanged(boolean)方法,使用FragmentTransaction中的hide(),show()时只会调用Fragment中的show和hidden状态,其他生命周期不会调用。
Activity类中的onWindowFocusChanged(boolean),onNewIntent(intent)等回调方法;
TextView类中的setTransformationMethod(TransformationMethod)方法,可用来实现“显示密码”功能
PageTransformer接口,用来自定义ViewPager页面切换动画,用setPageTransformer(boolean, PageTransformer)方法来进行设置;
apache提供的一系列jar包:commons-lang.jar,commons-collections.jar,commons-beanutils.jar等,里面很多方法可能是你曾经用几十几百行代码实现过的,但是执行效率或许要差很多,比如:ArrayUtils,StringUtils……;
ActivityOptions——方便的定义两个Activity切换的动画,使用ActivityOptionsCompat 可以很好解决旧版本的兼容问题。
getParent().requestDisallowInterceptTouchEvent(true)——剥夺父view对touch事件的处理权,谁用谁知道。
HandlerThread——代替不停new Thread开子线程的重复体力写法。
IntentService——一个可以干完活后自己去死且不需要我们去管理子线程的Service
Executors. newSingleThreadExecutor()——返回一个线程池(这个线程池只有一个线程),这个线程池可以在线程死后(或发生异常时)重新启动一个线程来替代原来的线程继续执行下去
android:animateLayoutChanges=“true”——LinearLayout中添加View的动画的办法,支持通过setLayoutTransition()自定义动画。
AsyncQueryHandler——异步的查询操作帮助类,可以处理增删改(ContentProvider提供的数据)
ViewFlipper——实现多个view的切换(循环),可自定义动画效果,且可针对单个切换指定动画。
includeFontPadding=“false”——TextView默认上下是有一定的padding的,有时候我们可能不需要上下这部分留白,加上它即可。
Messenger——基于消息的进程间通信的方式
EditText.setImeOptions——使用EditText弹出软键盘时,修改回车键的显示内容(一直很讨厌用回车键来交互,所以之前一直不知道这玩意儿)
java8中新增的LocalDate和LocalTime接口——Date虽然是个万能接口,但是它真的不好用,有了这俩,终于可以愉快的处理日期时间了。
WeakHashMap——直接使用HashMap有时候会带来内存溢出的风险,使用WaekHashMap实例化Map。当使用者不再有对象引用的时候,WeakHashMap将自动被移除对应Key值的对象。
设置TextView跑马灯效果,单行显示的时候不要用Lines=1,而要用singleLine=“true”
Palette——可用于提取一张图片的颜色。
ViewDragHelper——用来处理触摸事件的神器
View.getContext
在Android框架中,有两种类别的Context,分别是Application Context和Activity Context
Application Context:存在于应用的整个生命周期,只要应用存在,Application Context就存在,并且是唯一的。当应用被销毁了,Application Context才被销毁。
Activity Context:存在于Activity的整个生命周期,当onDestroy()执行后,Activity Context也被销毁。
getApplication():虽然它返回的是Application对象,但Application类继承自Context,所以它可以用来提供Application Context;
getApplicationContext():返回Application Context;
getBaseContext():返回Activity Context;
MainActivity.this:表示MainActivity对象,一般用在内部类中指示外面的this,如果在内部类直接用this,指示的是内部类本身。因为MainActivity继承Activity,而Activity继承Context,所以它也可以用来提供Activity Context;
this:表示当前对象;当它表示MainActivity时,也可以用来提供Activity Context,原因同上。
getContext():这个是View类中提供的方法,在继承了View的类中才可以调用,返回的是当前View运行在哪个Activity Context中。前面的3个方法可以在Activity中调用。
View.post——方便在非UI线程对界面进行修改,与Handler的作用类似。并且由于post的Runnable会保证在该View绘制完成的前提下才调用,所以一般也可以用于获取View的宽高。
setUserVisibleHintFragment()——Fragment在配合PagerAdapter使用的时候可以重写 此方法,然后根据参数的布尔值(true的话表示当前Fragment对用户可见),来执行一些逻辑。
android:clipToPadding——设置父view是否允许其子view在它的padding(这里指的是父View的padding)中绘制。
举个实际场景吧:假如有个ListView,我们想要在初始位置时,第一项Item离顶部有10dp的距离,就可以在ListView的布局中加入android:clipToPadding=“false” android:paddingTop="10dp"即可。
RecyclerView的Layoutmanager可以直接申明在xml中
ViewConfiguration.getScaledTouchSlop()——触发移动事件的最小距离,自定义View处理touch事件的时候,有的时候需要判断用户是否真的存在move,系统提供了这样的方法。
onTrimMemory——在Activity中重写此方法,会在内存紧张的时候回调(支持多个级别),便于我们主动的进行资源释放,避免OOM。
TextView.setCompoundDrawablePadding——代码设置TextView的drawable padding。
ImageSwitcher——可以用来做图片切换的一个类,类似于幻灯片。
Log.wtf()的意思是What a Terrible Failure
使用RenderScript虚化图片效果。
如果想把一个view保存为Bitmap,正常情况下用第一种方法就可以了,但是如果是ScrollView,则必须采用第二种方法。
当Activity LauncherMode 为singleTask和singleInstance时,使用startActivityForResult会立马返回,不能正常调用。
popupWindow.setFocusable(true)——当PopupWindow中有EditText控件时,因为Popupwindow 默认没有获取到焦点,需要手动设置焦点,这样子view才能获取到事件的监听。
popWindow.setBackgroundDrawable(new BitmapDrawable())——PopupWindow默认点击外部的时候不消失,需要对PopupWindow 设置一个背景图
android中的序列化官方推荐Parceble,其实Parceble最好用于内存之间数据的交换,如果要把数据写入硬盘的话,推荐实现Serializable
tools:—— tools标签可以很好的帮助开发者实时预览xml的效果,通过tools:background可以预览控件所占的控件,tools:visibility可以把一个gone的控件在预览的时候展示出来,并且运行以后tools标签的内容不会展示出来。
ContextCompat.getColor(context, R.color.color_name)——替换getResources().getColor()方法
图片的资源文件官方推荐只把launcher放在mipmap文件夹下面,而app用到的资源文件建议放在drawable下面。
android:windowSoftInputMode=“adjustResize”—— 如果你在manifest中把一个activity设置成 ,那么ScrollView(或者其它可伸缩的ViewGroups)会缩小,从而为软键盘腾出空间。
在Android 4.0以后,在Manifest.xml中静态注册的广播,程序安装后必须启动一次才能接收到广播,比如你的应用监听开机启动的广播,必须要你的程序被运行过才能监听到
Activity的onDestroy方法调用时机是不确定的(有时候离开界面很久之后才会调用onDestroy方法),应该避免指望通过onDestroy方法去释放与Activity相关的资源,否则会导致一些随机bug
.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提交
git rm -r --cached .
git add .
git commit -m 'update .gitignore'
Android上的应用切换按钮列出的其实不是应用而是Task,所以你会看到有的应用在切换视图里有多个任务。如果你的应用中有逻辑上相互独立的部分,或者想在多窗口环境下并排显示应用的两个不同部分,这种情况就适合多任务了。使用manifest属性(静态)或者 intent flags(动态)可以实现这一点。
Context类中的createPackageContext(packageName, flags)——可用来获取指定包名应用程序的Context对象。
View类中的getLocationInWindow(int[])方法和getLocationOnScreen(int[])——获取View在窗口/屏幕中的位置;
Android中的四大组件千万不要通过new的方式创建出来。
测试app的时候,我们大都想要将debug和release版本同时安装到手机里,可以通过在gradle中修改applicationid来实现
android {
buildTypes {
debug {
applicationIdSuffix '.debug'
versionNameSuffix '-DEBUG'
}
release {
//...
}
}
}
TextInputLayout passwordToggleEnabled——在大多数的登陆界面中,都提供了用户是否让密码可见的选项,并且可以通过 passwordToggleDrawable 设置图标。
SnapHelper——在Support Library 24.2.0中增加RecyclerView在快速滚动时的回调接口,SnapHelper是官方的一个实现OnFlingListener的 一个抽象类,LinearSnapHelper 则是一个完整的实现。LinearSnapHelper默认实现的功能是类似ViewPager,在滚动结束后,会选择列表某一条居中展示(这里有开始位置展示,或者结束位置显示点我)。
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(linearLayoutManager);
LinearSnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
Android中推荐使用的数据结构 :
ArrayMap in place of HashMap
ArraySet in place of HashSet
SparseArray in place of HashMap
SparseBooleanArray in place of HashMap
SparseIntArray in place of HashMap
SparseLongArray in place of HashMap
LongSparseArray in place of HashMap
生成GUID(由于java中只能生成UUID,所以这里要转换一下)
return UUID.randomUUID().toString().toUpperCase().replaceAll("-", "");
在assert文件夹下存放单个文件的大小不能超过1M,如果读取超过1M的文件会报 “Data exceeds UNCOMPRESS_DATA_MAX (1314625 vs 1048576)” 的IOException。如果一定要存储,可以分割文件,再去合并文件。
当前Activity的onPause方法执行结束后才会执行下一个Activity的onCreate方法,所以在onPause方法中不适合做耗时较长的工作,这会影响到页面之间的跳转效率。
不要通过Bundle传递大块的数据,否则会报TransactionTooLargeException异常
使用Toast时,建议定义一个全局的Toast对象,这样可以避免连续显示Toast时不能取消上一次Toast消息的情况(如果你有连续弹出Toast的情况,避免使用Toast.makeText)。
尽量避免给window和Activity同时都设置了背景,这样会造成过渡绘制,可以通过在给Activity设置主题时,去掉windowBackground背景的方式减少一层过渡绘制,有时候为了避免进入Activity时会黑屏或者白屏(和主题有关),会在给Activity设置主题的时候给window设置背景,如果这种情况下给Activity也设置了背景,是会增加一倍内存的:
- @null
public class Colors {
@IntDef({RED, GREEN, YELLOW})
//声明必要的int常量,使用@IntDef修饰LightColors,参数设置为待枚举的集合
@Retention(RetentionPolicy.SOURCE)
//使用@Retention(RetentionPolicy.SOURCE)指定注解仅存在与源码中,不加入到class文件中
public @interface LightColors{}
//声明一个注解为LightColors
public static final int RED = 0;
public static final int GREEN = 1;
public static final int YELLOW = 2;
}
//用法
private void setColor(@Colors.LightColors int color) {
Log.d("MainActivity", "setColor color=" + color);
}
//调用的该方法的时候
setColor(Colors.GREEN);
PathInterpolatorCompat ——创建各种插值曲线,举个非常简单的例子:
Path path = new Path();
path.cubicTo(0.2f, 0f, 0.1f, 1f, 0.5f, 1f);
path.lineTo(1f, 1f);
ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, 500);
animator.setInterpolator(PathInterpolatorCompat.create(path));
animator.start();
public static boolean isNetWorkAvailable(final Context context) {
try {
Runtime runtime = Runtime.getRuntime();
Process pingProcess = runtime.exec("/system/bin/ping -c 1 www.baidu.com");
int exitCode = pingProcess.waitFor(); //0 代表连通,2代表不通
return (exitCode == 0);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
@Override
public void onBackPressed() {
moveTaskToBack(false);
}
activity生命周期