Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> 關於Android Force Close 出現的原因 以及解決方法,androidforce

關於Android Force Close 出現的原因 以及解決方法,androidforce

編輯:關於android開發

關於Android Force Close 出現的原因 以及解決方法,androidforce


一、原因:

forceclose,意為強行關閉,當前應用程序發生了沖突。

NullPointExection(空指針),IndexOutOfBoundsException(下標越界),就連Android API使用的順序錯誤也可能導致(比如setContentView()之前進行了findViewById()操作)等等一系列未捕獲異常

 

二、如何避免

如何避免彈出Force Close窗口 ,可以實現Thread.UncaughtExceptionHandler接口的uncaughtException方法 代碼如下:

public class MainActivity extends Activity implements Thread.UncaughtExceptionHandler,
        View.OnClickListener {
    private List<String> mList = new ArrayList<String>();
    private Button btn;

    private int pid;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.i("tag", "--->>onCreate");

        initView();
        //設置處理異常的handler
        Thread.setDefaultUncaughtExceptionHandler(this);

    }

    /**
     * 初始化控件
     */
    private void initView() {
        btn = (Button) findViewById(R.id.main_btn);
        btn.setOnClickListener(this);

    }

    @Override
    public void uncaughtException(Thread arg0, Throwable arg1) {
        // TODO Auto-generated method stub
        Log.i("tag",  "截獲到forceclose,異常原因為:" + "\n" +
                arg1.toString()+"  Thread:"+arg0.getId());
       // finish();//結束當前activity
        android.os.Process.killProcess(android.os.Process.myPid());
    }

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub
        switch (arg0.getId()) {
            case R.id.main_btn:
                mList.get(1) ;//產生異常
                break;

            default:
                break;
        }
    }
    @Override
    protected void onPause() {
        super.onPause();
        Log.i("tag", "--》onpause");
    }

    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        super.onStop();
        Log.i("tag", "--->onstop");
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        Log.i("tag", "-->ondestroy");
    }
}

 再補充一句,想要哪個線程可以處理未捕獲異常,Thread.setDefaultUncaughtExceptionHandler( this); 這句代碼都要在那個線程中執行一次

在uncaughtException方法中,第一個參數是線程,第二個參數是異常。

 public void uncaughtException(Thread arg0, Throwable arg1) {
        // TODO Auto-generated method stub
        Log.i("tag",  "截獲到forceclose,異常原因為:" + "\n" +
                arg1.toString()+"  Thread:"+arg0.getId());
       // finish();//結束當前activity
        android.os.Process.killProcess(android.os.Process.myPid());
    }

 接下來,看log日志的結果:

08-0918:50:27.87410739-10739/example.com.force_anrI/tag:--->>onCreate 08-0918:50:31.66410739-10739/example.com.force_anrI/tag:截獲到forceclose,異常原因為: java.lang.IndexOutOfBoundsException:Invalidindex1,sizeis0Thread:1

成功捕獲到了異常,而且activity也退出了,可是並不是安全退出,因為當你再次點擊打開apk時,發現程序無響應。

為了解決上述問題,我在uncaughtException方法裡將進程殺死,殺死進程有好多中方法,在此列舉一個自殺式方法

修改如下: 

@Override  
    public void uncaughtException(Thread arg0, Throwable arg1) {  
        // TODO Auto-generated method stub  
        Log.i("tag",  "截獲到forceclose,異常原因為:" + "\n" +  
                   arg1.toString());  
         android.os.Process.killProcess(android.os.Process.myPid()); //
    }  其他程序未變。。

3,我們不僅可以在主線程中這麼做,還可以在子線程中進行:

然後在activity的生命周期中開啟子線程,監聽未捕獲異常的發生。

class MyRunnable extends Thread implements Thread.UncaughtExceptionHandler {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            Thread.setDefaultUncaughtExceptionHandler(this);
        }
        @Override
        public void uncaughtException(Thread arg0, Throwable arg1) {
            // TODO Auto-generated method stub
            Log.i("tag", "childThread:截獲到forceclose,異常原因為:" + "\n" +
                    arg1.toString()+"  Thread->"+arg0.getId()+" 本線程id->"+Thread.currentThread().getId()+" "+
                    Thread.currentThread().getName());
            android.os.Process.killProcess(android.os.Process.myPid());
        }

    }

  這裡有個問題:我們明明是在子線程捕獲的異常,但是怎麼Thread的id->1 本線程id->1,為什麼線程是主線程!在下面探討這個問題。

08-09 19:02:47.734 14483-14483/example.com.force_anr I/tag: --->>onCreate
08-09 19:02:51.304 14483-14483/example.com.force_anr I/tag: childThread:截獲到forceclose,異常原因為:
java.lang.IndexOutOfBoundsException: Invalid index 1, size is 0 Thread->1 本線程id->1 main

  

4.解決第三步的問題

我們重寫子線程:在子線程裡設置異常,同時別忘把activity中的捕獲異常的代碼和發生異常的代碼刪除。

class MyRunnable extends Thread implements Thread.UncaughtExceptionHandler {

        int a[];
        @Override
        public void run() {
            // TODO Auto-generated method stub
            Thread.setDefaultUncaughtExceptionHandler(this);
            int i = a[0];//異常
        }
        @Override
        public void uncaughtException(Thread arg0, Throwable arg1) {
            // TODO Auto-generated method stub
            Log.i("tag", "childThread:截獲到forceclose,異常原因為:" + "\n" +
                    arg1.toString()+"  Thread->"+arg0.getId()+" 本線程id->"+Thread.currentThread().getId()+" "+
                    Thread.currentThread().getName());
            android.os.Process.killProcess(android.os.Process.myPid());
        }

    }

  在啟動程序看到下面的log:

08-09 19:08:20.124 16308-16308/example.com.force_anr I/tag: --->>onCreate
08-09 19:08:20.124 16308-16341/example.com.force_anr I/tag: childThread:截獲到forceclose,異常原因為:
                                                            java.lang.NullPointerException: Attempt to read from null array  Thread->44829 本線程id->44829 Thread-44829
08-09 19:08:20.254 16349-16349/example.com.force_anr I/tag: --->>onCreate
08-09 19:08:20.354 16376-16376/example.com.force_anr I/tag: --->>onCreate
08-09 19:08:20.354 16376-16411/example.com.force_anr I/tag: childThread:截獲到forceclose,異常原因為:
                                                            java.lang.NullPointerException: Attempt to read from null array  Thread->44839 本線程id->44839 Thread-44839

 好像是嘗試啟動了兩次,看下Thread已經變了。所以在這個方法uncaughtException(Thread arg0, Throwable arg1)中的arg0指的是發生異常的那個Thread,而不一定是uncaughtException注冊的Thread。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved