Android 常見(jiàn)的錯(cuò)誤日志及相應(yīng)的解決方案總結(jié)

之前整理過(guò)一些關(guān)于常見(jiàn)的錯(cuò)誤日志,基于生產(chǎn)的bug日志系統(tǒng),我這邊會(huì)不間斷的更新錯(cuò)誤日志及相應(yīng)的解決方案,拋磚引玉(PS:也許解決的方法有點(diǎn)菜揩晴,希望大家能給出更優(yōu)的解決方案及意見(jiàn)反饋,非常歡迎贪磺,相互學(xué)習(xí)共同進(jìn)步)

android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

at android.view.ViewRootImpl.setView(ViewRootImpl.java:635)
at android.view.ColorViewRootImpl.setView(ColorViewRootImpl.java:60)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:321)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:86)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:1262)
at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:1110)
at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:1069)

以上bug出現(xiàn)的原因是因?yàn)镻opupWindow需要依附在一個(gè)創(chuàng)建好的Activity上硫兰,那么出現(xiàn)這個(gè)異常就說(shuō)明此時(shí)你的Activity還沒(méi)有創(chuàng)建好,出現(xiàn)這種情況寒锚,很可能是在onCreate()或者是onStart()中調(diào)用導(dǎo)致的劫映。
下面有兩種方法可以解決這個(gè)問(wèn)題:

方法一:重載Activity的onWindowFocusChanged方法违孝,然后在里面實(shí)現(xiàn)相應(yīng)的邏輯如下:

public void onWindowFocusChanged(boolean hasFocus) {  
    super.onWindowFocusChanged(hasFocus);  
    if(hasFocus) {  
        //執(zhí)行PopupWindow相應(yīng)的操作
    }  
}

下面給大家看下這個(gè)方法的源碼,有興趣的小伙伴可以看看

 /**
 * Called when the current {@link Window} of the activity gains or loses
 * focus.  This is the best indicator of whether this activity is visible
 * to the user.  The default implementation clears the key tracking
 * state, so should always be called.
 * 
 * <p>Note that this provides information about global focus state, which
 * is managed independently of activity lifecycles.  As such, while focus
 * changes will generally have some relation to lifecycle changes (an
 * activity that is stopped will not generally get window focus), you
 * should not rely on any particular order between the callbacks here and
 * those in the other lifecycle methods such as {@link #onResume}.
 * 
 * <p>As a general rule, however, a resumed activity will have window
 * focus...  unless it has displayed other dialogs or popups that take
 * input focus, in which case the activity itself will not have focus
 * when the other windows have it.  Likewise, the system may display
 * system-level windows (such as the status bar notification panel or
 * a system alert) which will temporarily take window input focus without
 * pausing the foreground activity.
 *
 * @param hasFocus Whether the window of this activity has focus.
 * 
 * @see #hasWindowFocus()
 * @see #onResume
 * @see View#onWindowFocusChanged(boolean)
 */
public void onWindowFocusChanged(boolean hasFocus) {
}

方法二:上面的那種方法是需要實(shí)現(xiàn)Activity的一個(gè)方法并在方法中做操作泳赋,一般我們?cè)陧?xiàng)目中會(huì)在一些邏輯里面showPopupWindow或者其他的雌桑,那這樣就會(huì)影響一些,然后我們就針對(duì)這個(gè)源碼祖今,追溯一下會(huì)發(fā)現(xiàn)另外一個(gè)方法:hasWindowFocus

 /**
 * Returns true if this activity's <em>main</em> window currently has window focus.
 * Note that this is not the same as the view itself having focus.
 * 
 * @return True if this activity's main window currently has window focus.
 * 
 * @see #onWindowAttributesChanged(android.view.WindowManager.LayoutParams)
 */
public boolean hasWindowFocus() {
Window w = getWindow();
if (w != null) {
View d = w.getDecorView();
if (d != null) {
return d.hasWindowFocus();
}
}
return false;
}

查看上面的源碼校坑,我們會(huì)發(fā)現(xiàn),我們可以直接使用hasWindowFocus來(lái)判斷當(dāng)前的Activity有沒(méi)有創(chuàng)建好千诬,再去做其他操作耍目;以上就是這個(gè)錯(cuò)誤日志相應(yīng)的解決方案嗦锐,如果還有其他的希望大家補(bǔ)充谈况。

java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity

這個(gè)問(wèn)題是在使用Glide的時(shí)候生產(chǎn)上面爆出來(lái)的做鹰,如果遇到其他相似的錯(cuò)誤也可以試一下,以下有兩種解決方案:

方法一:參考博文
在使用Glide的地方加上這個(gè)判斷峡继;Util是系統(tǒng)自帶的;

if(Util.isOnMainThread()) {
Glide.with(AppUtil.getContext()).load``(R.mipmap.iclunch).error(R.mipmap.cuowu).into(imageView);
}

在使用的Glide的界面的生命周期onDestroy中添加如下代碼:

@Override
protected void onDestroy() {
super.onDestroy();
if(Util.isOnMainThread()) {
Glide.with(this).pauseRequests();
}
}

上面Destroy中with(this),改成with(AppUtil.getContext());
不然會(huì)報(bào): java.lang.IllegalStateException: Activity has been destroyed
擴(kuò)展:
Glide.with(AppUtil.getContext()).resumeRequests()和 Glide.with(AppUtil.getContext()).pauseRequests()的區(qū)別:
1.當(dāng)列表在滑動(dòng)的時(shí)候喘帚,調(diào)用pauseRequests()取消請(qǐng)求负溪;
2.滑動(dòng)停止時(shí)蓬推,調(diào)用resumeRequests()恢復(fù)請(qǐng)求烫幕;
另外Glide.clear():當(dāng)你想清除掉所有的圖片加載請(qǐng)求時(shí),這個(gè)方法可以用到敞映。
ListPreloader:如果你想讓列表預(yù)加載的話较曼,可以試試這個(gè)類。
請(qǐng)記住一句話:不要再非主線程里面使用Glide加載圖片振愿,如果真的使用了捷犹,請(qǐng)把context參數(shù)換成getApplicationContext;

方法二:使用Activity提供的isFinishing和isDestroyed方法冕末,來(lái)判斷當(dāng)前的Activity是不是已經(jīng)銷(xiāo)毀了或者說(shuō)正在finishing萍歉,下面貼出來(lái)相應(yīng)的源碼:

/**
 * 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;
}

附上項(xiàng)目相應(yīng)的源碼,希望有所幫助:

final WeakReference<ImageView> imgBankLogoWeakReference = new WeakReference<>(imgBankLogo);
    final WeakReference<ImageView> imgBankBgWeakReference = new WeakReference<>(imgBankBg);
    ImageView imgBankLogoTarget = imgBankLogoWeakReference.get();
    ImageView imgBankBgTarget = imgBankBgWeakReference.get();
    if (imgBankLogoTarget != null && imgBankBgTarget != null) {
        if (!(isFinishing() || isDestroyed())) {
            Glide.with(xxx.this).load(_bankCardInfo.getBankInfo().getBankLogo())
                    .centerCrop().into(imgBankLogoTarget);
            Glide.with(xxx.this).load(_bankCardInfo.getBankInfo().getBankBg())
                    .centerCrop().into(imgBankBgTarget);
        }
    }

java.lang.IllegalStateException: Could not find a method OnButtonClick(View) in the activity class android.view.ContextThemeWrapper for onClick handler on view class android.widget.ImageView with id 'img_apply_result'

at android.view.View$1.onClick(View.java:4061)
at android.view.View.performClick(View.java:4848)
at android.view.View$PerformClick.run(View.java:20262)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5714)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:984)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
Caused by: java.lang.NoSuchMethodException: OnButtonClick [class android.view.View]
at java.lang.Class.getMethod(Class.java:664)
at java.lang.Class.getMethod(Class.java:643)
at android.view.View$1.onClick(View.java:4054)

解決方法:

以上的錯(cuò)誤日志出現(xiàn)的有點(diǎn)low,但是呢有時(shí)候部分人還是容易忽略:我們一般在Activity或fragment等Java代碼中使用資源文件時(shí)档桃,例如:在Java代碼中對(duì)一個(gè)Imageview附一張圖片枪孩,我們不能img.setImageResource(圖片相應(yīng)的資源ID);需要img.setImageResource(context.getResources().getDrawable(圖片相應(yīng)的資源ID));需要先獲取文件資源,再去拿圖片藻肄,但是剛剛寫(xiě)的那個(gè)方法現(xiàn)在已經(jīng)過(guò)時(shí)了蔑舞,下面我貼出Google官方給出的最新的方法img.setImageDrawable(ContextCompat.getDrawable(context, imgResId));其實(shí)setImageDrawable是最省內(nèi)存高效的,如果擔(dān)心圖片過(guò)大或者圖片過(guò)多影響內(nèi)存和加載效率,可以自己解析圖片然后通過(guò)調(diào)用setImageDrawable方法進(jìn)行設(shè)置

java.lang.NoClassDefFoundError: android.app.AppOpsManager

Appops是Application Operations的簡(jiǎn)稱,是關(guān)于應(yīng)用權(quán)限管理的一套方案嘹屯,但這里的應(yīng)用指的是系統(tǒng)應(yīng)用攻询,這些API不對(duì)第三方應(yīng)用開(kāi)放。Appops的兩個(gè)重要組成部分是AppOpsManager和AppOpsService,它們是典型的客戶端和服務(wù)端設(shè)計(jì)州弟,通過(guò)Binder跨進(jìn)程調(diào)用钧栖。AppOpsManager提供標(biāo)準(zhǔn)的API供APP調(diào)用低零,但google有明確說(shuō)明,大部分只針對(duì)系統(tǒng)應(yīng)用拯杠。AppOpsService是做最終檢查的系統(tǒng)服務(wù)掏婶,它的注冊(cè)名字是appops, 應(yīng)用可以類似于

mAppOps=(AppOpsManager)getContext().getSystemService(Context.APP_OPS_SERVICE);的方式來(lái)獲取這個(gè)服務(wù)。

解決方法:這個(gè)api是在19新加入的阴挣,所以要注意加個(gè)判斷气堕,參考項(xiàng)目代碼如下:

判斷是否開(kāi)啟通知權(quán)限(解釋比較好的博客推薦

private boolean isNotificationEnabled(Context context) {

    String CHECK_OP_NO_THROW = "checkOpNoThrow";
    String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";
    if (Build.VERSION.SDK_INT < 19) {
        return true;
    }
    try {
        AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        ApplicationInfo appInfo = context.getApplicationInfo();
        String pkg = context.getApplicationContext().getPackageName();
        int uid = appInfo.uid;
        Class appOpsClass = null;
        /* Context.APP_OPS_MANAGER */
        appOpsClass = Class.forName(AppOpsManager.class.getName());
        Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE,
                String.class);
        Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);

        int value = (Integer) opPostNotificationValue.get(Integer.class);
        return ((Integer) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) == AppOpsManager.MODE_ALLOWED);

    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (NoClassDefFoundError e) {
        e.printStackTrace();
    }
    return false;
}

java.lang.SecurityException: getDeviceId: Neither user 10185 nor current process has android.permission.READ_PHONE_STATE.

這里的getDeviceId可能是獲取系統(tǒng)狀態(tài)或內(nèi)容的操作,需要授予android.permission.READ_PHONE_STATE 權(quán)限畔咧,首先我們來(lái)看一下危險(xiǎn)權(quán)限組

我們會(huì)發(fā)現(xiàn)android.permission.READ_PHONE_STATE 這個(gè)權(quán)限在PHONE組里面茎芭,在Android M版本及以后,當(dāng)你的應(yīng)用運(yùn)行在Android6.0系統(tǒng)上如果設(shè)置targetSdkVersion小于23的時(shí)候誓沸,它也會(huì)默認(rèn)采用以前的權(quán)限管理機(jī)制梅桩,當(dāng)你的targetSdkVersion大于等于23的時(shí)候且在Andorid6.0(M)系統(tǒng)上,它會(huì)采用新的這套權(quán)限管理機(jī)制拜隧。相關(guān)動(dòng)態(tài)權(quán)限爬坑這塊可以看一下之前的博文(傳送門(mén))
宿百,當(dāng)你配置了targetSdkVersion>=23時(shí),默認(rèn)第一次安裝會(huì)打開(kāi)android.permission.READ_PHONE_STATE這個(gè)權(quán)限洪添,部分手機(jī)親測(cè)垦页,那樣依舊可以獲取getDeviceId,但這個(gè)權(quán)限是可見(jiàn)的,用戶在后續(xù)是可以關(guān)閉的干奢。當(dāng)用戶關(guān)閉了這個(gè)權(quán)限痊焊,下次進(jìn)來(lái)會(huì)動(dòng)態(tài)彈出授權(quán)頁(yè)面提醒用戶授權(quán),如果用戶依舊關(guān)閉權(quán)限將獲取不到DeviceId忿峻。但是國(guó)產(chǎn)手機(jī)的各種自定義導(dǎo)致部分手機(jī)會(huì)出現(xiàn)動(dòng)態(tài)權(quán)限返回0薄啥,(PS:當(dāng)用戶禁止了權(quán)限,返回回調(diào)還是為已授權(quán)逛尚,例如:OPPO meizu等兼容)垄惧,這樣就尷尬了,如果我們拿到用戶已經(jīng)授權(quán)(但實(shí)際上是禁止的)就去調(diào)用

TelephonyManager tm = (TelephonyManager) getApplicationContext()
                .getSystemService(Context.TELEPHONY_SERVICE);
        _clientInfo.setDeviceId(tm.getDeviceId());

就會(huì)閃退绰寞,目前這邊處理的思路為:第一次如果拿到就放在SharedPreferences里面存起來(lái)到逊,當(dāng)下次用戶再次關(guān)閉權(quán)限也不用擔(dān)心報(bào)錯(cuò);

java.util.ConcurrentModificationExceptionat java.util.ArrayList$ArrayListIterator.next(ArrayList.java:578)

at com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter.serialize(DefaultTypeAdapters.java:637)
at com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter.serialize(DefaultTypeAdapters.java:624)
at com.google.gson.JsonSerializationVisitor.findAndInvokeCustomSerializer(JsonSerializationVisitor.java:184)
at com.google.gson.JsonSerializationVisitor.visitUsingCustomHandler(JsonSerializationVisitor.java:160)
at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:101)
at com.google.gson.JsonSerializationContextDefault.serialize(JsonSerializationContextDefault.java:62)
at com.google.gson.JsonSerializationContextDefault.serialize(JsonSerializationContextDefault.java:53)
at com.google.gson.Gson.toJsonTree(Gson.java:220)
at com.google.gson.Gson.toJson(Gson.java:260)
at com.google.gson.Gson.toJson(Gson.java:240)

在ArrayList.addAll()中對(duì)傳進(jìn)來(lái)的參數(shù)沒(méi)有做null判斷克握,于是蕾管,在調(diào)用collection.toArray()函數(shù)的時(shí)候就拋異常了,activity就崩潰了

在使用ArrayList.addAll()的時(shí)候一定要注意傳入的參數(shù)會(huì)不會(huì)出現(xiàn)為null的情況菩暗,如果有掰曾,那么我們可以做以下判斷

if (collection!= null)
mInfoList.addAll(Collection<? extends E> collection);

如果為null,就不執(zhí)行下面的了停团,我們也不能確保是不是存在null的情況旷坦,所以為了確保不會(huì)出錯(cuò)掏熬,在前面加個(gè)判斷是一個(gè)有經(jīng)驗(yàn)的程序員該做的。以上錯(cuò)誤日志的原因秒梅,可以看下源碼大家就可以理解了:(這個(gè)問(wèn)題雖小但容易忽略旗芬,希望各位注意)

/**
 * Appends all of the elements in the specified collection to the end of
 * this list, in the order that they are returned by the
 * specified collection's Iterator.  The behavior of this operation is
 * undefined if the specified collection is modified while the operation
 * is in progress.  (This implies that the behavior of this call is
 * undefined if the specified collection is this list, and this
 * list is nonempty.)
 *
 * @param c collection containing elements to be added to this list
 * @return <tt>true</tt> if this list changed as a result of the call
 * @throws NullPointerException if the specified collection is null
 */
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
    int numNew = a.length;
ensureCapacity(size + numNew);  // Increments modCount
    System.arraycopy(a, 0, elementData, size, numNew);
    size += numNew;
return numNew != 0;
}

android.content.ActivityNotFoundException: Unable to find explicit activity class {com.android.browser/com.android.browser.BrowserActivity}; have you declared this activity in your AndroidManifest.xml?

以上錯(cuò)誤日志出現(xiàn)的背景是調(diào)用系統(tǒng)自帶的瀏覽器出現(xiàn)的,原因是因?yàn)椴糠质謾C(jī)設(shè)備商更改Android原生自帶的com.android.browser/com.android.browser.BrowserActivity自己弄了一個(gè)其他的捆蜀,例如疮丛,生產(chǎn)就出現(xiàn)一款手機(jī) HTC 802t,這款手機(jī)自帶瀏覽器的代碼包名為:com.htc.sense.browser,看到這塊是不是想吐槽一下辆它,所以說(shuō)如果直接寫(xiě)以下代碼誊薄,就會(huì)出現(xiàn)以上錯(cuò)誤日志:

 Intent intent = new Intent();
    intent.setAction("android.intent.action.VIEW");
    intent.addCategory(Intent.CATEGORY_BROWSABLE);
    Uri contentUri = Uri.parse(_versionInfo.getAppUrl());
    intent.setData(contentUri);
 intent.setComponent(new ComponentName("com.android.browser", "com.android.browser.BrowserActivity"));

解決方案(PS:獲取系統(tǒng)安裝的所有的瀏覽器應(yīng)用 過(guò)濾):

Intent intent = new Intent();
    intent.setAction("android.intent.action.VIEW");
    intent.addCategory(Intent.CATEGORY_BROWSABLE);
    Uri contentUri = Uri.parse(_versionInfo.getAppUrl());
    intent.setData(contentUri);
    // HTC com.htc.sense.browser
    List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(intent,
            PackageManager.MATCH_DEFAULT_ONLY);//通過(guò)查詢,獲得所有ResolveInfo對(duì)象.  
    for (ResolveInfo resolveInfo : resolveInfos) {
        browsers.add(resolveInfo.activityInfo.packageName);
        System.out.println(resolveInfo.activityInfo.packageName);
    }
    if (browsers.contains("com.android.browser")) {
        intent.setComponent(new ComponentName("com.android.browser", "com.android.browser.BrowserActivity"));
    }
    context.startActivity(intent);

android.os.FileUriExposedException/NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getPath()' on a null object reference:

上述錯(cuò)誤日志是Android 7.0應(yīng)用間共享文件(FileProvider)兼容的問(wèn)題锰茉,后續(xù)會(huì)出一篇博文來(lái)講解:
下面提供代碼:

/**
 * 適配7.0及以上
 * 
 * @param context
 * @param file
 * @return
 */
private static Uri getUriForFile(Context context, File file) {
    if (context == null || file == null) {
        throw new NullPointerException();
    }
    Uri uri;
    if (Build.VERSION.SDK_INT >= 24) {
        uri = FileProvider.getUriForFile(context.getApplicationContext(), "xxx.fileprovider", file);
    } else {
        uri = Uri.fromFile(file);
    }
    return uri;
}

AndroidManifest中配置provider:

<provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.crfchina.market.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true" >
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/filepaths" />
    </provider>

下面是很久之前的備忘的呢蔫,也貼出來(lái)給大家分享一下§可能涉及到其他博文的內(nèi)容片吊,如有發(fā)現(xiàn),麻煩私信协屡,我后續(xù)加上 ……

android java.net.UnknownHostException: Unable to resolve host "...": No address associated 錯(cuò)誤

解決方法:

  • (1)手機(jī)3G或者WIFI沒(méi)有開(kāi)啟

  • (2).Manifest文件沒(méi)有標(biāo)明網(wǎng)絡(luò)訪問(wèn)權(quán)限
    如果確認(rèn)網(wǎng)絡(luò)已經(jīng)正常連接并且還是出這種錯(cuò)誤的話,那么請(qǐng)看下你的Manifest文件是否標(biāo)明應(yīng)用需要網(wǎng)絡(luò)訪問(wèn)權(quán)限,如果沒(méi)標(biāo)明的話,也訪問(wèn)不了網(wǎng)絡(luò),也會(huì)造成這種情況的.

    //網(wǎng)絡(luò)訪問(wèn)權(quán)限

    <uses-permission android:name="android.permission.INTERNET" />

java.lang.NullPointerException: missing IConnectivityManager

at com.android.internal.util.Preconditions.checkNotNull(Preconditions.java:52)
at android.net.ConnectivityManager.<init>(ConnectivityManager.java:919)
at android.app.ContextImpl$11.createService(ContextImpl.java:387)
at android.app.ContextImpl$ServiceFetcher.getService(ContextImpl.java:278)
at android.app.ContextImpl.getSystemService(ContextImpl.java:1676)
at android.content.ContextWrapper.getSystemService(ContextWrapper.java:540)
at com.crfchina.market.util.NetUtil.getNetworkState(NetUtil.java:28)

錯(cuò)誤日志產(chǎn)生原因:

Android里面內(nèi)存泄漏問(wèn)題最突出的就是Activity的泄漏俏脊,而泄漏的根源大多在于單例的使用,也就是一個(gè)靜態(tài)實(shí)例持有了Activity的引用肤晓。靜態(tài)變量的生命周期與應(yīng)用(Application)是相同的联予,而Activity生命周期通常比它短,也就會(huì)造成在Activity生命周期結(jié)束后材原,還被引用導(dǎo)致無(wú)法被系統(tǒng)回收釋放。
生成靜態(tài)引用內(nèi)存泄漏可能有兩種情況:

1. 應(yīng)用級(jí):應(yīng)用程序代碼實(shí)現(xiàn)的單例沒(méi)有很好的管理其生命周期季眷,導(dǎo)致Activity退出后仍然被引用余蟹。
2. 系統(tǒng)級(jí):Android系統(tǒng)級(jí)的實(shí)現(xiàn)的單例,被應(yīng)用不小心錯(cuò)誤調(diào)用(當(dāng)然你也可以認(rèn)為是系統(tǒng)層實(shí)現(xiàn)地不太友好)子刮。

這個(gè)主要講下系統(tǒng)級(jí)的情況威酒,這樣的情況可能也有很多,舉個(gè)最近發(fā)現(xiàn)的問(wèn)題ConnectivityManager挺峡。
通常我們獲取系統(tǒng)服務(wù)時(shí)采用如下方式:
context.getSystemService()
在Android6.0系統(tǒng)上葵孤,如果這里的Context如果是Activity的實(shí)例,那么即使你什么也不干也會(huì)造成內(nèi)存泄漏橱赠。
這個(gè)Context在ConnectivityManager 創(chuàng)建時(shí)傳入尤仍,這個(gè)Context在StaticOuterContextServiceFetcher中由ContextImpl對(duì)象轉(zhuǎn)換為OuterContext,與就是Activity對(duì)象狭姨,所以最終ConnectivityManager的單實(shí)例持有了Activity的實(shí)例引用宰啦。這樣即使Activity退出后仍然無(wú)法釋放苏遥,導(dǎo)致內(nèi)存泄漏。
這個(gè)問(wèn)題僅在6.0上出現(xiàn)赡模,在5.1上ConnectivityManager實(shí)現(xiàn)為單例但不持有Context的引用田炭,在5.0有以下版本ConnectivityManager既不為單例,也不持有Context的引用漓柑。
其他服務(wù)沒(méi)認(rèn)真研究教硫,不確定有沒(méi)有這個(gè)問(wèn)題。不過(guò)為了避免類似的情況發(fā)生辆布,
最好的解決辦法就是:

解決方案:

獲取系統(tǒng)服務(wù)getSystemService時(shí)使用ApplicationContext
context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);

java.lang.IllegalArgumentException: View not attached to window manager

錯(cuò)誤日志產(chǎn)生原因:

在延時(shí)線程里調(diào)用了ProgressDialog.dismiss瞬矩,但此時(shí)主Activity已經(jīng)destroy了。于是應(yīng)用崩潰谚殊,我寫(xiě)了一個(gè) SafeProgressDialog 來(lái)避免這個(gè)問(wèn)題丧鸯,主要原理是覆寫(xiě)dismiss方法,在ProgressDialog.dismiss之前判斷Activity是否存在嫩絮。

解決方案:

class SafeProgressDialog extends ProgressDialog
 {
    Activity mParentActivity;
     public SafeProgressDialog(Context context)
     {
         super(context);
         mParentActivity = (Activity) context;
 }
  
     @Override
     public void dismiss()
    {
        if (mParentActivity != null && !mParentActivity.isFinishing())
         {
            super.dismiss();    //調(diào)用超類對(duì)應(yīng)方法
         }
    }
 }

Android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.test.testFragment: make sure class name exists, is public, and has an empty constructor that is public

錯(cuò)誤日志產(chǎn)生原因及解決方案:

根據(jù)報(bào)錯(cuò)提示 “make sure class name exists, is public, and has an empty constructor that is public” 丛肢,若Fragement定義有帶參構(gòu)造函數(shù),則一定要定義public的默認(rèn)的構(gòu)造函數(shù)剿干。即可解決此問(wèn)題蜂怎。
除了他說(shuō)的public.還有一個(gè)就是弄個(gè)空的構(gòu)造函數(shù)。
例如我是這樣定義了我的fragment置尔。帶有了構(gòu)造函數(shù)

public TestFragment(int index){
mIndex = index;
}

然后我添加了一個(gè)這樣的構(gòu)造函數(shù)

public TestFragment(){
}

java.lang.IllegalStateException: Unable to get package info for com.crfchina.market; is package not installed?

錯(cuò)誤日志產(chǎn)生原因:

簡(jiǎn)單的卸載app 沒(méi)有卸載干凈杠步,然后再次運(yùn)行,當(dāng)dalvik重新安裝。apk文件并試圖重用以前的活動(dòng)從同一個(gè)包


好了目前就總結(jié)這么多榜轿,后續(xù)還會(huì)繼續(xù)更新補(bǔ)充幽歼!畢竟太長(zhǎng)也沒(méi)有人愿意耐下心去看,以上也是曾經(jīng)遇到過(guò)坑谬盐,希望有遇到的兄弟能從中受益甸私!歡迎大家貼一些內(nèi)容作為補(bǔ)充,相互學(xué)習(xí)共同進(jìn)步……

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末飞傀,一起剝皮案震驚了整個(gè)濱河市皇型,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌砸烦,老刑警劉巖弃鸦,帶你破解...
    沈念sama閱讀 205,874評(píng)論 6 479
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異幢痘,居然都是意外死亡唬格,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,151評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)西轩,“玉大人员舵,你說(shuō)我怎么就攤上這事∨号希” “怎么了马僻?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,270評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)注服。 經(jīng)常有香客問(wèn)我韭邓,道長(zhǎng),這世上最難降的妖魔是什么溶弟? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,137評(píng)論 1 278
  • 正文 為了忘掉前任女淑,我火速辦了婚禮,結(jié)果婚禮上辜御,老公的妹妹穿的比我還像新娘鸭你。我一直安慰自己,他們只是感情好擒权,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,116評(píng)論 5 370
  • 文/花漫 我一把揭開(kāi)白布袱巨。 她就那樣靜靜地躺著,像睡著了一般碳抄。 火紅的嫁衣襯著肌膚如雪愉老。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 48,935評(píng)論 1 283
  • 那天剖效,我揣著相機(jī)與錄音嫉入,去河邊找鬼。 笑死璧尸,一個(gè)胖子當(dāng)著我的面吹牛咒林,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播爷光,決...
    沈念sama閱讀 38,261評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼映九,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了瞎颗?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,895評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤捌议,失蹤者是張志新(化名)和其女友劉穎哼拔,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體瓣颅,經(jīng)...
    沈念sama閱讀 43,342評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡倦逐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,854評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宫补。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片檬姥。...
    茶點(diǎn)故事閱讀 37,978評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡曾我,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出健民,到底是詐尸還是另有隱情抒巢,我是刑警寧澤,帶...
    沈念sama閱讀 33,609評(píng)論 4 322
  • 正文 年R本政府宣布秉犹,位于F島的核電站蛉谜,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏崇堵。R本人自食惡果不足惜型诚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,181評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸳劳。 院中可真熱鬧狰贯,春花似錦、人聲如沸赏廓。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,182評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)楚昭。三九已至栖袋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間抚太,已是汗流浹背塘幅。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,402評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尿贫,地道東北人电媳。 一個(gè)月前我還...
    沈念sama閱讀 45,376評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像庆亡,于是被迫代替她去往敵國(guó)和親匾乓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,677評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,494評(píng)論 25 707
  • afinalAfinal是一個(gè)android的ioc又谋,orm框架 https://github.com/yangf...
    passiontim閱讀 15,399評(píng)論 2 45
  • 看了《七月與安生》忽然好想你拼缝,尤其是在這樣的失意迷茫的初秋。 從16歲到26歲彰亥,十年過(guò)得好快好快咧七。在那個(gè)小城市,我...
    豆丁小魚(yú)Fishbean閱讀 303評(píng)論 0 0
  • 少不入川的慢節(jié)奏任斋,讓成都成為世人向往的一座休閑城市继阻,以茶會(huì)友童叟無(wú)欺,成都的茶館不啻為一方重要的社交場(chǎng)所。記得多年...
    布衣沙彌閱讀 208評(píng)論 0 0
  • 初次知道簡(jiǎn)書(shū)是偶然吧∧粒看到一個(gè)同學(xué)在空間里發(fā)了2016年的總結(jié)卓研,以圖片的方式呈現(xiàn)給我們,不經(jīng)意間發(fā)現(xiàn)了有簡(jiǎn)書(shū)二字背蟆,...
    卡卡槑閱讀 184評(píng)論 0 0