Android 開發中不得不知道的 Tips 集合 (第三波)

weixinjie發表於2017-07-08

相關文章 1.Android 開發中不得不知道的 Tips 集合 (持續更新 ing) 2.Android 開發中不得不知道的 Tips 集合 (第二波))

1.應用又崩潰啦!!!

開發過程中,受種種因素影響(機型適配問題、程式設計師技術功底等),已釋出上線的應用難免回出現Crash,如果我們不做處理,崩潰後系統會彈出對話方塊(xxx應用已停止).這時候使用者手一哆嗦就直接解除安裝了有木有。so,既然開發人員不能阻止Crash的出現,那就得從崩潰後的提示入手了,將對使用者的影響降到最低。

解決方案: 利用Thread的setDefaultUncaughtExceptionHandler方法,將未知的異常進行捕獲,然後友好的提示使用者,重新啟動應用。(伸手黨可直接拿走哈) 有圖有真相:

Android 開發中不得不知道的 Tips 集合 (第三波)

1.新建CrashHandler類,這個類負責捕獲未處理的異常

/**
 * Created by weixinjie on 2017/6/1.
 */

public class CrashHandler implements Thread.UncaughtExceptionHandler {
    private Thread.UncaughtExceptionHandler mDefaultHandler;
    public static final String TAG = "CatchExcep";
    SampleApplication application;

    public CrashHandler(SampleApplication application) {
        //獲取系統預設的UncaughtException處理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        this.application = application;
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(ex) && mDefaultHandler != null) {
            //如果使用者沒有處理則讓系統預設的異常處理器來處理
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                Log.e(TAG, "error : ", e);
            }
            Intent intent = new Intent(application.getApplicationContext(), MainActivity.class);
            PendingIntent restartIntent = PendingIntent.getActivity(
                    application.getApplicationContext(), 0, intent,
                    PendingIntent.FLAG_CANCEL_CURRENT);
            //退出程式
            AlarmManager mgr = (AlarmManager) application.getSystemService(Context.ALARM_SERVICE);
            mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000,
                    restartIntent); // 1秒鐘後重啟應用
            System.exit(0);
        }
    }

    /**
     * 自定義錯誤處理,收集錯誤資訊 傳送錯誤報告等操作均在此完成.
     *
     * @param ex
     * @return true:如果處理了該異常資訊;否則返回false.
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        //使用Toast來顯示異常資訊
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(application, "應用異常,正在重啟", Toast.LENGTH_LONG).show();
                Looper.loop();
            }
        }.start();
        return true;
    }
}


    /**
     * 自定義錯誤處理,收集錯誤資訊 傳送錯誤報告等操作均在此完成.
     *
     * @param ex
     * @return true:如果處理了該異常資訊;否則返回false.
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        //使用Toast來顯示異常資訊
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                ToastUtil.toastLong(R.string.error_for_restart);
                Looper.loop();
            }
        }.start();
        return true;
    }
}
複製程式碼

2.在應用的Application的onCreate方法中呼叫如下程式碼:

  @Override
    public void onCreate() {
        initCrashHandler();
    }

 private void initCrashHandler() {
        //設定該CrashHandler為程式的預設處理器
        CrashHandler catchExcep = new CrashHandler(this);
        Thread.setDefaultUncaughtExceptionHandler(catchExcep);
    }
複製程式碼

3.在清單檔案中將自定義的Application註冊一下.

2.為什麼要用IntentService而不用Thread

面試的時候大家經常會被問IntentService跟Thread有什麼區別吧?比如App升級的時候,去服務端下載apk包的時候為什麼要開一個IntertService而不是Thread. Answer:我們要從Android系統的5大程式級別來看待這個事情,分別為“前臺程式”,“可視程式”,“服務程式”,“後臺程式”,“空程式”.當系統的記憶體不足時,會根據程式的級別來回收這些程式.即回收的順序為:“空程式”->...->“前臺程式”.很明顯,如果使用者按下home鍵之後,我們的程式會變成一個後臺程式,此時很容易被系統回收掉,那我們們在Thread中所做的操作就白扯了,而如果我們開一個IntentService的話,我們的程式會變成一個Service程式,被回收的機率就大大降低了。 當然,這種問題我們不應該只停留在理論階段,應付面試是一方面,我們還是要多看系統的文件,這也是我等菜鳥通往高階工程師必不可少的一環。 祭上官方文件:https://developer.android.com/guide/components/processes-and-threads.html?hl=zh-cn (科學上網哈)

3.Gradle指令碼中已刪除的sdk,釋出release包的事後報NoClassDefFoundError錯誤

緣由:專案在內測階段用到了BugTags來指Bug (BugTags確實可以大大提高測試的效率,建議大家在內測階段接入他們的服務進行測試) ,釋出release版本的時候,為了減少包體,便將該sdk從gradle指令碼中剔除了。然後打出release包之後。一開啟就閃退,並且報如下錯誤

Android 開發中不得不知道的 Tips 集合 (第三波)
我當時就鬱悶了,Gradle指令碼中都刪了咋還報類找不到?然後花了一下午的時間挨個疑點進行排查——沒錯是新版的gradle的鍋。 解決方案: 找到 gradle --> wrapper --> gradle-wrapper.properties distributionUrl=https://services.gradle.org/distributions/gradle-2.14.1-all.zip android gradle build 外掛版本 classpath 'com.android.tools.build:gradle:2.2.3'

4.用adb進行wifi連結真機除錯(不需root呦)。

方案如下: 1.手機與你的電腦要在同一個區域網下 2.配置你電腦上的adb命令。不要告訴我你不會配,請自行百度哈。 3.用usb連結電腦跟手機,在命令視窗輸入:[ adb tcpip 5555 ]

Android 開發中不得不知道的 Tips 集合 (第三波)
4.檢視你手機的ip地址:設定-WLAN-[點選你正在使用的wifi],例如我手機的ip地址為: 192.168.31.237 5.在adb命令中輸入: adb connect 192.168.31.237

Android 開發中不得不知道的 Tips 集合 (第三波)
6.拔掉的usb線,以後就可以用wifi除錯這部手機啦。看下你的as中的Android Monitor模組,正常來說已經可以出現要除錯的手機了。(搞不定的叫我微信,或留言哈)

Android 開發中不得不知道的 Tips 集合 (第三波)

5.通往大牛的路上,怎能不看系統原始碼

前段時間專案趕,沒時間繼續我的看系統原始碼計劃,還好,現在專案進入正常迭代週期,我又有時間可以折騰原始碼啦。 推薦給大家一個Chrome外掛:https://chrome.google.com/webstore/search/Android%20SDK%20Reference%20Search%20 安裝之後,你用Chrome瀏覽器去Android Developer上查api的時候,會自動加入這麼一個東東,你就可以enjoy看系統原始碼帶給你的充實啦。

Android 開發中不得不知道的 Tips 集合 (第三波)
樓主用的Mac,用Sublime+CTag折騰了一套原始碼閱讀器,用了半年了感覺很棒。需要的同學留言,下次分享給大家哈。

About Me

contact way value
mail weixinjie1993@gmail.com
wechat W2006292
github https://github.com/weixinjie
blog https://juejin.im/user/57673c83207703006bb92bf6

相關文章