2017-01-13 5 views
1

Ich versuche mit AsyncTask mit inneren Klasse zu arbeiten. Aber ich habe ein Problem mit Leckspeicher. Also beschloss ich, einen Testcode zu schreiben, um herauszufinden, wo das Problem liegen könnte. In diesem Code unten habe ich versucht, eine Aufgabe auszuführen, die von 0 bis 100 zählt. Dann verließ ich die Aktivität, während die Aufgabe ausgeführt wurde. Ich habe eine _InterruptedException_ und Activity durchgesickert (mit Leak Canary), dann wurde meine App eingefroren, bis es abgestürzt ist. Ich konnte nicht verstehen, warum, weil die Aufgabe abgebrochen wurde, bevor ich die Aktivität verließ.Aktiviere beim Ausführen von AsyncTask kann Speicher auslaufen lassen?

Hier ist mein kleiner Beispielcode:

public class MainActivity extends AppCompatActivity { 
TextView textView; 
BackgroundTask _task; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    textView = (TextView) findViewById(R.id.textView); 

    _task = new BackgroundTask(textView); 
    _task.execute(); 
} 

@Override 
protected void onPause() { 
    _task.cancel(true); 
    super.onPause(); 
} 

@Override 
protected void onResume() { 
    if (_task.isCancelled()){ 
     _task = new BackgroundTask(textView); 
     _task.execute(); 
    } 
    super.onResume(); 
} 

private class BackgroundTask extends AsyncTask<Void, Integer, String> { 
    private WeakReference<TextView> _textView; 

    public BackgroundTask(TextView textView) { 
     this._textView = new WeakReference<TextView>(textView); 
    } 

    @Override 
    protected String doInBackground(Void... params) { 
     for (int i = 0; i <= 100; i++) 
      try { 
       Thread.sleep(1000); 
       publishProgress(i); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     return "DONE"; 
    } 

    @Override 
    protected void onProgressUpdate(Integer... values) { 
     TextView textView = _textView.get(); 
     if (textView != null) { 
      textView.setText(values[0] + " ."); 
     } 
     Log.d("==> ",values[0]+" "); 
    } 

    @Override 
    protected void onPostExecute(String result) { 
     TextView textView = _textView.get(); 
      if (textView != null) { 
      textView.setText(result); 
    } 
     //MainActivity.this.isFinishing(); 
    } 
    } 

} 

Hier mein log ist:

D/==>: 0 
D/==>: 1 
D/==>: 2 
W/System.err: java.lang.InterruptedException 
W/System.err:  at java.lang.Thread.sleep(Native Method) 
W/System.err:  at java.lang.Thread.sleep(Thread.java:1031) 
W/System.err:  at java.lang.Thread.sleep(Thread.java:985) 
W/System.err:  at com.example.longluong.test_app.MainActivity$BackgroundTask.doInBackground(MainActivity.java:58) 
W/System.err:  at com.example.longluong.test_app.MainActivity$BackgroundTask.doInBackground(MainActivity.java:47) 
W/System.err:  at android.os.AsyncTask$2.call(AsyncTask.java:295) 
W/System.err:  at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
W/System.err:  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
W/System.err:  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
W/System.err:  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
W/System.err:  at java.lang.Thread.run(Thread.java:818) 
I/art: Waiting for a blocking GC Explicit 
I/art: Starting a blocking GC Explicit 
I/art: Explicit concurrent mark sweep GC freed 343(27KB) AllocSpace objects, 0(0B) LOS objects, 82% free, 1267KB/7MB, paused 488us total 18.818ms 
I/art: hprof: heap dump "/storage/emulated/0/Download/leakcanary-com.example.longluong.test_app/0a1c4ebe-238f-4156-a317-ed8d454de769_pending.hprof" starting... 
I/art: hprof: heap dump completed (12MB) in 7.001s 
D/LeakCanary: In com.example.longluong.test_app:1.0:1. 
D/LeakCanary: * com.example.longluong.test_app.MainActivity has leaked: 
D/LeakCanary: * GC ROOT thread java.lang.Thread.<Java Local> (named 'AsyncTask #1') 
D/LeakCanary: * references com.example.longluong.test_app.MainActivity$BackgroundTask.this$0 
D/LeakCanary: * leaks com.example.longluong.test_app.MainActivity instance 
D/LeakCanary: * Retaining: 6.7 KB. 
D/LeakCanary: * Reference Key: 4db87806-d761-42c8-a874-9682d7477106 
D/LeakCanary: * Device: LENOVO Lenovo Lenovo TB2-X30F TB2-X30F 
D/LeakCanary: * Android Version: 6.0.1 API: 23 LeakCanary: 1.5 00f37f5 
D/LeakCanary: * Durations: watch=5055ms, gc=125ms, heap dump=7205ms, analysis=26304ms 
D/LeakCanary: * Details: 
D/LeakCanary: * Instance of java.lang.Thread 
D/LeakCanary: | static NANOS_PER_MILLI = 1000000 
D/LeakCanary: | static defaultUncaughtHandler = [email protected] (0x22c01180) 
D/LeakCanary: | static count = 902 
D/LeakCanary: | static MAX_PRIORITY = 10 
D/LeakCanary: | static $staticOverhead = byte[48]@1873454545 (0x6faaa5d1) 
D/LeakCanary: | static NORM_PRIORITY = 5 
D/LeakCanary: | static MIN_PRIORITY = 1 
D/LeakCanary: | contextClassLoader = [email protected] (0x22c02d80) 
D/LeakCanary: | daemon = false 
D/LeakCanary: | group = [email protected] (0x6f8e8818) 
D/LeakCanary: | hasBeenStarted = true 
D/LeakCanary: | id = 900 
D/LeakCanary: | inheritableValues = null 
D/LeakCanary: | interruptActions = [email protected] (0x22d84ba0) 
D/LeakCanary: | localValues = [email protected] (0x22d84bc0) 
D/LeakCanary: | lock = [email protected] (0x22c01100) 
D/LeakCanary: | name = [email protected] (0x22d83340) 
D/LeakCanary: | nativePeer = -1218480552 
D/LeakCanary: | parkBlocker = null 
D/LeakCanary: | parkState = 1 
D/LeakCanary: | priority = 5 
D/LeakCanary: | stackSize = 0 
D/LeakCanary: | target = [email protected] (0x22c001f0) 
D/LeakCanary: | uncaughtHandler = null 
D/LeakCanary: | shadow$_klass_ = java.lang.Thread 
D/LeakCanary: | shadow$_monitor_ = 0 
D/LeakCanary: * Instance of com.example.longluong.test_app.MainActivity$BackgroundTask 
D/LeakCanary: | static $staticOverhead = byte[16]@583275521 (0x22c41401) 
D/LeakCanary: | static serialVersionUID = 0 
D/LeakCanary: | static $change = null 
D/LeakCanary: | _textView = [email protected] (0x22d69fa0) 
D/LeakCanary: | this$0 = [email protected] (0x22c8d300) 
D/LeakCanary: | mCancelled = [email protected] (0x22d6c1a0) 
D/LeakCanary: | mFuture = [email protected] (0x22c020c0) 
D/LeakCanary: | mStatus = [email protected] (0x6f924e30) 
D/LeakCanary: | mTaskInvoked = [email protected] (0x22d6c1b0) 
D/LeakCanary: | mWorker = [email protected] (0x22c01120) 
D/LeakCanary: | shadow$_klass_ = com.example.longluong.test_app.MainActivity$BackgroundTask 
D/LeakCanary: | shadow$_monitor_ = 0 
D/LeakCanary: * Instance of com.example.longluong.test_app.MainActivity 
D/LeakCanary: | static $staticOverhead = byte[16]@584134657 (0x22d13001) 
D/LeakCanary: | static serialVersionUID = 0 
D/LeakCanary: | static $change = null 
D/LeakCanary: | _task = [email protected]8704 (0x22c001c0) 
D/LeakCanary: | textView = [email protected] (0x22d07800) 
D/LeakCanary: | mDelegate = [email protected] (0x22c0da60) 
D/LeakCanary: | mEatKeyUpEvent = false 
D/LeakCanary: | mResources = null 
D/LeakCanary: | mThemeId = 2131230877 
D/LeakCanary: | mCreated = true 
D/LeakCanary: | mFragments = [email protected] (0x22d6c1c0) 
D/LeakCanary: | mHandler = [email protected] (0x22d69fc0) 
D/LeakCanary: | mMediaController = null 
D/LeakCanary: | mNextCandidateRequestIndex = 0 
D/LeakCanary: | mOptionsMenuInvalidated = false 
D/LeakCanary: | mPendingFragmentActivityResults = [email protected] (0x22d69fe0) 
D/LeakCanary: | mReallyStopped = true 
D/LeakCanary: | mRequestedPermissionsFromFragment = false 
D/LeakCanary: | mResumed = false 
D/LeakCanary: | mRetaining = false 
D/LeakCanary: | mStopped = true 
D/LeakCanary: | mStartedActivityFromFragment = false 
D/LeakCanary: | mStartedIntentSenderFromFragment = false 
D/LeakCanary: | mActionBar = null 
D/LeakCanary: | mActionModeTypeStarting = 0 
D/LeakCanary: | mActivityInfo = [email protected] (0x22d66300) 
D/LeakCanary: | mActivityTransitionState = [email protected] (0x22d41ec0) 
D/LeakCanary: | mApplication = [email protected] (0x22d78040) 
D/LeakCanary: | mCalled = true 
D/LeakCanary: | mChangeCanvasToTranslucent = false 
D/LeakCanary: | mChangingConfigurations = false 
D/LeakCanary: | mComponent = [email protected] (0x22d6c1d0) 
D/LeakCanary: | mConfigChangeFlags = 0 
D/LeakCanary: | mCurrentConfig = [email protected] (0x22d6d100) 
D/LeakCanary: | mDecor = null 
D/LeakCanary: | mDefaultKeyMode = 0 
D/LeakCanary: | mDefaultKeySsb = null 
D/LeakCanary: | mDestroyed = true 
D/LeakCanary: | mDoReportFullyDrawn = false 
D/LeakCanary: | mEmbeddedID = null 
D/LeakCanary: | mEnableDefaultActionBarUp = false 
D/LeakCanary: | mEnterTransitionListener = [email protected] (0x6f8e9aa0) 
D/LeakCanary: | mExitTransitionListener = [email protected] (0x6f8e9aa0) 
D/LeakCanary: | mFinished = true 
D/LeakCanary: | mFragments = [email protected] (0x22d6c1e0) 
D/LeakCanary: | mHandler = [email protected] (0x22d78060) 
D/LeakCanary: | mHasCurrentPermissionsRequest = false 
D/LeakCanary: | mIdent = 115814648 
D/LeakCanary: | mInstanceTracker = [email protected] (0x22d6c1f0) 
D/LeakCanary: | mInstrumentation = [email protected] (0x22d37830) 
D/LeakCanary: | mIntent = [email protected] (0x22d41f00) 
D/LeakCanary: | mLastNonConfigurationInstances = null 
D/LeakCanary: | mMainThread = [email protected] (0x22c03100) 
D/LeakCanary: | mManagedCursors = [email protected] (0x22d78080) 
D/LeakCanary: | mManagedDialogs = null 
D/LeakCanary: | mMenuInflater = null 
D/LeakCanary: | mParent = null 
D/LeakCanary: | mReferrer = null 
D/LeakCanary: | mResultCode = 0 
D/LeakCanary: | mResultData = null 
D/LeakCanary: | mResumed = false 
D/LeakCanary: | mSearchEvent = null 
D/LeakCanary: | mSearchManager = null 
D/LeakCanary: | mStartedActivity = false 
D/LeakCanary: | mStopped = true 
D/LeakCanary: | mTemporaryPause = false 
D/LeakCanary: | mTitle = [email protected] (0x22d780a0) 
D/LeakCanary: | mTitleColor = 0 
D/LeakCanary: | mTitleReady = true 
D/LeakCanary: | mToken = [email protected] (0x22d780c0) 
D/LeakCanary: | mTranslucentCallback = null 
D/LeakCanary: | mUiThread = [email protected] (0x733cc258) 
D/LeakCanary: | mVisibleBehind = false 
D/LeakCanary: | mVisibleFromClient = true 
D/LeakCanary: | mVisibleFromServer = true 
D/LeakCanary: | mVoiceInteractor = null 
D/LeakCanary: | mWindow = [email protected] (0x22c4c0a0) 
D/LeakCanary: | mWindowAdded = true 
D/LeakCanary: | mWindowManager = [email protected] (0x22d780e0) 
D/LeakCanary: | mInflater = [email protected] (0x22d68340) 
D/LeakCanary: | mOverrideConfiguration = null 
D/LeakCanary: | mResources = [email protected] (0x22d37880) 
D/LeakCanary: | mTheme = [email protected] (0x22d78100) 
D/LeakCanary: | mThemeResource = 2131230877 
D/LeakCanary: | mBase = [email protected] (0x22d66380) 
D/LeakCanary: | shadow$_klass_ = com.example.longluong.test_app.MainActivity 
D/LeakCanary: | shadow$_monitor_ = 1266075474 
D/LeakCanary: * Excluded Refs: 
D/LeakCanary: | Field: android.view.inputmethod.InputMethodManager.mNextServedView 
D/LeakCanary: | Field: android.view.inputmethod.InputMethodManager.mServedView 
D/LeakCanary: | Field: android.view.inputmethod.InputMethodManager.mServedInputConnection 
D/LeakCanary: | Field: android.view.inputmethod.InputMethodManager.mCurRootView 
D/LeakCanary: | Field: android.os.UserManager.mContext 
D/LeakCanary: | Field: android.net.ConnectivityManager.sInstance 
D/LeakCanary: | Field: android.view.Choreographer$FrameDisplayEventReceiver.mMessageQueue (always) 
D/LeakCanary: | Thread:FinalizerWatchdogDaemon (always) 
D/LeakCanary: | Thread:main (always) 
D/LeakCanary: | Thread:LeakCanary-Heap-Dump (always) 
D/LeakCanary: | Class:java.lang.ref.WeakReference (always) 
D/LeakCanary: | Class:java.lang.ref.SoftReference (always) 
D/LeakCanary: | Class:java.lang.ref.PhantomReference (always) 
D/LeakCanary: | Class:java.lang.ref.Finalizer (always) 
D/LeakCanary: | Class:java.lang.ref.FinalizerReference (always) 
+0

Vielleicht weil Sie eine Ansicht von der Aktivität verwenden, die in der Nähe war? – Jonas452

+0

Fehlercode senden. Drücken Sie auf den Zurück-Knopf oder nach Hause, um die Aktivität zu verlassen? –

+0

Sie möchten eine Hintergrundaufgabe ausführen und wenn ich zur zweiten Aktivität gehe, sollte diese Aufgabe nicht abgebrochen werden, oder? –

Antwort

1

Nach InterruptedException Ihre for Schleife noch Looping, wenn Sie Ihren Fortschritt Thread veröffentlichen, so wird abgebrochen Sie müssen überprüfen, ob Ihr Thread abgebrochen wurde oder nicht.

Wenn Ihre Anwendung abstürzt, haben Sie immer noch eine WeakReference Ihrer TextView, deshalb haben Sie ein Speicherleck. Sie müssen Ihre WeakReference in onPostExecute und onCancelled löschen.

Ihr Wechsel:

doInBackground zu

@Override 
protected String doInBackground(Void... params) { 
    for (int i = 0; i <= 100; i++){ 
     if(isCancelled()) 
      break; 
     try { 
      Thread.sleep(1000); 
      // After 1 second may be thread is cancelled 
      if(!isCancelled()) 
       publishProgress(i); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
      break; 
     } 
    } 
    return "DONE"; 
} 

onProgressUpdate zu

@Override 
protected void onProgressUpdate(Integer... values) { 
    if(_textView != null){ 
     TextView textView = _textView.get(); 
     if (textView != null) { 
      textView.setText(values[0] + " ."); 
     } 
     Log.d("==> ",values[0]+" "); 
    } 
} 

onPostExecute zu

@Override 
protected void onPostExecute(String result) { 
    // safe check 
    if(_textView != null){ 
     TextView textView = _textView.get(); 
     if (textView != null) { 
      textView.setText(result); 
     _textView.clear(); 
    } 
    _textView = null; 
} 

Und fügen onCancelled

@Override 
protected void onCancelled() { 
    // safe check 
    super.onCancelled(); 
    if(_textView != null) 
     _textView.clear(); 
    _textView = null; 
} 
+0

Danke für deine Antwort. Aber bist du sicher, dass _textView.crear() in onProgressUpdate() in der richtigen Position ist? Weil mein TextView nicht ändert –

+0

Und nach dem Verlassen der Aktivität habe ich noch eine ** W/System.err: java.lang.InterruptedException ** in meinem Protokoll. Ist das normal? –

+1

Sorry, mein Fehler, entferne '_textView.clear()' von 'onProgressUpdate'. Ja log ist normal. –

Verwandte Themen