Android开发实用技巧

前言

好久没写文章了,赶紧趁着有时间水一篇。今天要分享的是个人在实际开发中积累的那些实用小技巧,以后有新发现也会继续更新下去,方便查看。

正文

1. 简单方法加动效,拒绝生硬

(1) 如何用一行代码加动效:

android:animateLayoutChanges="true"

开启系统默认动画效果,在每次布局发生变化的时候生效,让布局的变化过渡看起来更自然。试一下,有惊喜!

(2) 自定义LayoutAnimation:

//初始化LayoutAnimationController
private LayoutAnimationController getAnimationController() {
    final int duration = 180; //动画时长
    AnimationSet set = new AnimationSet(true);
     
 //渐变动画
    Animation animation = new AlphaAnimation(0.0f, 1.0f);
    animation.setDuration(duration);
    set.addAnimation(animation);
 //平移动画
    animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,-1.0f, Animation.RELATIVE_TO_SELF, 0.0f);
    animation.setDuration(duration);
    set.addAnimation(animation);

    LayoutAnimationController animationController = new LayoutAnimationController(set, 0.5f);
    animationController.setOrder(LayoutAnimationController.ORDER_NORMAL);
    return animationController;
}
...
//设置LayoutAnimation
View.setLayoutAnimation(getAnimationController();
//显式调用LayoutAnimation
View.startLayoutAnimation();

LayoutAnimation作用于View,可以自定义组合动画,显式调用动画。若对系统动画不满意,可以根据自己的需求写出动画效果。

2. 一行代码加入点击波纹扩散效果
android:foreground="?android:attr/selectableItemBackground"
3. 屏蔽快速点击、重复事件

用于屏蔽快速点击,短时间内的重复多余的事件、双击退出等,避免手动管理。

/**
 * 屏蔽快速重复操作事件
 */
private static long lastTime;
private static final int MIN_DELAY_TIME = 1000;

public static boolean isQuickOperating() {
    boolean flag = true;
    long currentTime = System.currentTimeMillis();
    if ((currentTime - lastTime) >= MIN_DELAY_TIME) {
        flag = false;
    }
    lastTime = currentTime;
    return flag;
}
4. 判断当前Activity是否已被销毁

通常,在网络请求的回调中会对UI进行更新操作,弹出吐司等。但是在网络状态不佳的情况下,等到异步结果回调时,当前Activity已经被系统销毁,此时进行UI操作就会造成异常,弹出的吐司也让人疑惑。所以,在网络回调中需要先判断一下当前Activity状态,若已销毁,直接return。代码片段如下:

if (this.isFinishing() || this.isDestroyed()) {
            return;
        }

源码及注释:

    /**
  * Check to see whether this activity is in the process of finishing,
  * either because you called {@link #finish} on it or someone else
  * has requested that it finished.  This is often used in
  * {@link #onPause} to determine whether the activity is simply pausing or
  * completely finishing.
  *
  * @return If the activity is finishing, returns true; else returns false.
  *
  * @see #finish
  */
 public boolean isFinishing() {
     return mFinished;
 }

 /**
  * Returns true if the final {@link #onDestroy()} call has been made
  * on the Activity, so this instance is now dead.
  */
 public boolean isDestroyed() {
     return mDestroyed;
 }
5. 使用SystemClock.sleep()替代Thread.sleep()

两者使用方法跟作用都类似,但SystemClock.sleep()不会立即抛出InterruptedException,中断事件被推迟到下一个可中断操作中。 可以说非常适合简单的延迟操作了,不用频繁。(说的好像Thread.sleep()方法Try Catch了Exception真的会做什么一样......

6. 线程池的简单使用

原始粗放的形式:

new Thread(new Runnable() {
 @Override
 public void run() {
        // TODO
     Log.e("run");
 }
}).start();

合理科学的形式:

Runnable command = new Runnable(){
 @Override
 public void run(){
     // TODO
     Log.e("run");
 }
};
//定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
fixedThreadPool.execute(command);
//可缓存线程池,如果线程池长度超出需求,可灵活回收空闲线程,若无线程可回收,则新建
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.execute(command);
//定长线程池,支持定时及周期性任务执行
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);
// 2000ms后执行
scheduledExecutorService.schedule(command,2000,TimeUnit.MILLISECONDS);
// 延迟10ms后,每隔1000ms执行一次command
scheduledExecutorService.scheduleAtFixedRate(command,10,1000,TimeUnit.MILLISECONDS);
//单线程化线程池,使用唯一工作线程来执行任务,保证所有任务按顺序执行
ExecutorService singleThreadExecutor = Executor.newSingleThreadExecutor;
singleThreadExecutor.execute(command);
7. 自定义BuildConfig字段,方便查看版本信息
buildTypes {
        release {
            minifyEnabled true 
            shrinkResources true
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
         //自定义BuildConfig字段,可通过BuildConfig.buildTime取出,方便查看编译信息
            buildConfigField("String", "buildTime", "\"" + new Date().format("yyyy/MM/dd HH:mm:ss") + "\"")
        }
 }   

在应用内埋个彩蛋,结合VERSION_CODE、VERSION_NAME、BUILD_TYPE,就可以方便查看当前APP的版本相关信息了!

8. 模拟点击View

这个功能不多说了,实用!

 /**
 * 模拟点击,点击该View的xy坐标(5,5)
 *
 * @param view 模拟点击的View
 */
public static void simulateTouch(View view) {
 
    final long downTime = SystemClock.uptimeMillis();
    int[] ints = new int[2];
    view.getLocationOnScreen(ints);
    view.dispatchTouchEvent(MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN,
            ints[0] + 5, ints[1] + 5, 0));
    view.dispatchTouchEvent(MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_UP,
            ints[0] + 5, ints[1] + 5, 0));
         
}
9. 使用tools属性工具预览布局

tools属性仅对IDE生效,并不会影响最终打包的应用;
比如TextView需要预览内容,可以使用tools:text属性,如果ImageView默认不显示,而你又要预览,就可以使用tools:visibility属性,避免改动android:visibility过后忘记改回去的尴尬。其他更多属性可以自己去尝试了。

 
 

结语

最后,春节马上就要到了,祝大家节日快乐!新的一年,新的进步!

参考资料

  • Java(Android)线程池
  • 《Android开发艺术探索》

你可能感兴趣的:(Android开发实用技巧)