Android Force Close 出現(xiàn)的異常原因分析及解決方法
一、原因:
forceclose,意為強行關(guān)閉,當(dāng)前應(yīng)用程序發(fā)生了沖突。
NullPointExection(空指針),IndexOutOfBoundsException(下標(biāo)越界),就連Android API使用的順序錯誤也可能導(dǎo)致(比如setContentView()之前進行了findViewById()操作)等等一系列未捕獲異常
二、如何避免
如何避免彈出Force Close窗口 ,可以實現(xiàn)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(); //設(shè)置處理異常的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();//結(jié)束當(dāng)前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) ;//產(chǎn)生異常 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); 這句代碼都要在那個線程中執(zhí)行一次
在uncaughtException方法中,第一個參數(shù)是線程,第二個參數(shù)是異常。
public void uncaughtException(Thread arg0, Throwable arg1) { // TODO Auto-generated method stub Log.i("tag", "截獲到forceclose,異常原因為:" + "\n" + arg1.toString()+" Thread:"+arg0.getId()); // finish();//結(jié)束當(dāng)前activity android.os.Process.killProcess(android.os.Process.myPid()); }
接下來,看log日志的結(jié)果:
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也退出了,可是并不是安全退出,因為當(dāng)你再次點擊打開apk時,發(fā)現(xiàn)程序無響應(yīng)。
為了解決上述問題,我在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的生命周期中開啟子線程,監(jiān)聽未捕獲異常的發(fā)生。
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.解決第三步的問題
我們重寫子線程:在子線程里設(shè)置異常,同時別忘把activity中的捕獲異常的代碼和發(fā)生異常的代碼刪除。
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已經(jīng)變了。所以在這個方法uncaughtException(Thread arg0, Throwable arg1)中的arg0指的是發(fā)生異常的那個Thread,而不一定是uncaughtException注冊的Thread。
以上所述是小編給大家介紹的Android Force Close 出現(xiàn)的異常原因分析及解決方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
Android自定義ScrollView實現(xiàn)阻尼回彈
這篇文章主要為大家詳細介紹了Android自定義ScrollView實現(xiàn)阻尼回彈,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04Android 中 SwipeLayout一個展示條目底層菜單的側(cè)滑控件源碼解析
這篇文章主要介紹了Android 中 SwipeLayout一個展示條目底層菜單的側(cè)滑控件源碼解析,需要的朋友可以參考下2016-12-12Android 深入探究自定義view之流式布局FlowLayout的使用
FlowLayout(int align, int hgap, int vgap)創(chuàng)建一個新的流布局管理器,它具有指定的對齊方式以及指定的水平和垂直間隙,意思就是說從左上角開始添加原件,依次往后排,第一行擠滿了就換一行接著排2021-11-11Android設(shè)置當(dāng)TextView中的文字超過TextView的容量時用省略號代替
這篇文章主要介紹了Android設(shè)置當(dāng)TextView中的文字超過TextView的容量時用省略號代替 ,需要的朋友可以參考下2017-03-03Android開發(fā)之ToggleButton實現(xiàn)開關(guān)效果示例
這篇文章主要介紹了Android開發(fā)之ToggleButton實現(xiàn)開關(guān)效果的方法,結(jié)合實例形式分析了ToggleButton控件實現(xiàn)開關(guān)效果的布局與功能相關(guān)操作技巧,需要的朋友可以參考下2017-07-07