Android Force Close 出現(xiàn)的異常原因分析及解決方法
一、原因:
forceclose,意為強(qiáng)行關(guān)閉,當(dāng)前應(yīng)用程序發(fā)生了沖突。
NullPointExection(空指針),IndexOutOfBoundsException(下標(biāo)越界),就連Android API使用的順序錯(cuò)誤也可能導(dǎo)致(比如setContentView()之前進(jìn)行了findViewById()操作)等等一系列未捕獲異常
二、如何避免
如何避免彈出Force Close窗口 ,可以實(shí)現(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,異常原因?yàn)椋? + "\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");
}
}
再補(bǔ)充一句,想要哪個(gè)線程可以處理未捕獲異常,Thread.setDefaultUncaughtExceptionHandler( this); 這句代碼都要在那個(gè)線程中執(zhí)行一次
在uncaughtException方法中,第一個(gè)參數(shù)是線程,第二個(gè)參數(shù)是異常。
public void uncaughtException(Thread arg0, Throwable arg1) {
// TODO Auto-generated method stub
Log.i("tag", "截獲到forceclose,異常原因?yàn)椋? + "\n" +
arg1.toString()+" Thread:"+arg0.getId());
// finish();//結(jié)束當(dāng)前activity
android.os.Process.killProcess(android.os.Process.myPid());
}
接下來(lái),看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,異常原因?yàn)椋?/p>
java.lang.IndexOutOfBoundsException:Invalidindex1,sizeis0Thread:1
成功捕獲到了異常,而且activity也退出了,可是并不是安全退出,因?yàn)楫?dāng)你再次點(diǎn)擊打開(kāi)apk時(shí),發(fā)現(xiàn)程序無(wú)響應(yīng)。
為了解決上述問(wèn)題,我在uncaughtException方法里將進(jìn)程殺死,殺死進(jìn)程有好多中方法,在此列舉一個(gè)自殺式方法
修改如下:
@Override
public void uncaughtException(Thread arg0, Throwable arg1) {
// TODO Auto-generated method stub
Log.i("tag", "截獲到forceclose,異常原因?yàn)椋? + "\n" +
arg1.toString());
android.os.Process.killProcess(android.os.Process.myPid()); //
}
其他程序未變。。
3,我們不僅可以在主線程中這么做,還可以在子線程中進(jìn)行:
然后在activity的生命周期中開(kāi)啟子線程,監(jiān)聽(tīng)未捕獲異常的發(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,異常原因?yàn)椋? + "\n" +
arg1.toString()+" Thread->"+arg0.getId()+" 本線程id->"+Thread.currentThread().getId()+" "+
Thread.currentThread().getName());
android.os.Process.killProcess(android.os.Process.myPid());
}
}
這里有個(gè)問(wèn)題:我們明明是在子線程捕獲的異常,但是怎么Thread的id->1 本線程id->1,為什么線程是主線程!在下面探討這個(gè)問(wèn)題。
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,異常原因?yàn)椋? java.lang.IndexOutOfBoundsException: Invalid index 1, size is 0 Thread->1 本線程id->1 main
4.解決第三步的問(wèn)題
我們重寫子線程:在子線程里設(shè)置異常,同時(shí)別忘把a(bǔ)ctivity中的捕獲異常的代碼和發(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,異常原因?yàn)椋? + "\n" +
arg1.toString()+" Thread->"+arg0.getId()+" 本線程id->"+Thread.currentThread().getId()+" "+
Thread.currentThread().getName());
android.os.Process.killProcess(android.os.Process.myPid());
}
}
在啟動(dòng)程序看到下面的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,異常原因?yàn)椋? 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,異常原因?yàn)椋? java.lang.NullPointerException: Attempt to read from null array Thread->44839 本線程id->44839 Thread-44839
好像是嘗試啟動(dòng)了兩次,看下Thread已經(jīng)變了。所以在這個(gè)方法uncaughtException(Thread arg0, Throwable arg1)中的arg0指的是發(fā)生異常的那個(gè)Thread,而不一定是uncaughtException注冊(cè)的Thread。
以上所述是小編給大家介紹的Android Force Close 出現(xiàn)的異常原因分析及解決方法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- C#判斷字符串是否是數(shù)字(實(shí)例)
- C#自動(dòng)判斷Excel版本使用不同的連接字符串
- C#判斷一個(gè)字符串是否包含另一個(gè)字符串的方法
- C#判斷字符串是否存在字母及字符串中字符的替換實(shí)例
- C#實(shí)現(xiàn)判斷字符串中是否包含中文的方法
- C#中判斷、驗(yàn)證字符串是否為日期格式的實(shí)現(xiàn)代碼
- C#中判斷字符串是全角還是半角的實(shí)現(xiàn)代碼
- c#中判斷字符串是不是數(shù)字或字母的方法
- C# 判斷字符串第一位是否為數(shù)字
- C# 判斷字符串為空的幾種辦法
- asp.ent(C#)中判斷空字符串的3種方法以及性能分析
- C#判斷字符串是否是int/double(實(shí)例)
相關(guān)文章
Android Studio 導(dǎo)入開(kāi)源項(xiàng)目的正確姿勢(shì)及注意事項(xiàng)
這篇文章主要介紹了Android Studio 導(dǎo)入開(kāi)源項(xiàng)目的正確姿勢(shì)及注意事項(xiàng),需要的朋友參考下吧2018-03-03
Android Messenger實(shí)現(xiàn)進(jìn)程間雙向通信
這篇文章主要為大家詳細(xì)介紹了Messenger實(shí)現(xiàn)進(jìn)程間雙向通信,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05
Android自定義View實(shí)現(xiàn)打字機(jī)效果
最近在做Android開(kāi)發(fā)的時(shí)候,需要做類似于打字機(jī)打字的效果,字一個(gè)一個(gè)地蹦出來(lái),顯示每一個(gè)字都帶有打字的聲音?,F(xiàn)在分享給大家,有需要的可以參考借鑒。2016-08-08
Android usb設(shè)備權(quán)限查詢及自動(dòng)獲取詳解流程
本篇文章介紹了我想要獲取Android系統(tǒng)usb設(shè)備使用權(quán)限時(shí)遇到的問(wèn)題,以及解決該問(wèn)題的過(guò)程及思路,通讀本篇對(duì)大家的學(xué)習(xí)或工作具有一定的價(jià)值,需要的朋友可以參考下2021-10-10
淺談android Fragment橫豎屏翻轉(zhuǎn)對(duì)重新加載的要求
下面小編就為大家分享一篇淺談android Fragment橫豎屏翻轉(zhuǎn)對(duì)重新加載的要求,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Android ShareSDK快速實(shí)現(xiàn)分享功能
這篇文章主要介紹了Android ShareSDK快速實(shí)現(xiàn)分享功能的相關(guān)資料,需要的朋友可以參考下2016-02-02
利用SurfaceView實(shí)現(xiàn)下雨與下雪動(dòng)畫效果詳解(Kotlin語(yǔ)法)
這篇文章主要給大家介紹了關(guān)于利用SurfaceView實(shí)現(xiàn)下雨與下雪動(dòng)畫效果的相關(guān)資料,需要一些基本的View知識(shí)和會(huì)一些基礎(chǔ)Kotlin語(yǔ)法,文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-09-09

