2012-04-16 88 views
5

我已將我的AsyncTask轉換爲AsyncTaskLoader(主要是爲了處理配置更改)。我有一個TextView我正在使用作爲進度狀態並在AsyncTask中使用onProgressUpdate來更新它。它看起來並不像AsyncTaskLoader具有等效的,所以在loadInBackground(在AsyncTaskLoader)我使用的是這樣的:從AsyncTaskLoader更新UI

getActivity().runOnUiThread(new Runnable() { 
    public void run() { 
     ((TextView)getActivity().findViewById(R.id.status)).setText("Updating..."); 
    } 
}); 

我在Fragment用這個,這就是爲什麼我使用getActivity()。這項工作非常好,除非發生配置更改,例如更改屏幕方向。我的AsyncTaskLoader繼續運行(這就是爲什麼我使用的是AsyncTaskLoader),但runOnUiThread似乎跳過了。

不確定爲什麼它被跳過,或者這是從AsyncTaskLoader更新UI的最佳方式。

UPDATE:

我最終回覆到一個AsyncTask,因爲它似乎更適合於用戶界面更新。希望他們可以將AsyncTaskAsyncTaskLoader合併。

回答

4

這實際上是可能的。您實質上需要繼承AsyncTaskloader的子類並實現publishMessage()方法,該方法將使用Handler將進度消息傳遞給實現ProgressListener(或任何您想調用它的接口)的任何類。

爲例下載此:http://www.2shared.com/file/VW68yhZ1/SampleTaskProgressDialogFragme.html(如果它下線給我發短信) - 這是基於的http://habrahabr.ru/post/131560/

+0

我認爲這是一個非常聰明的黑客攻擊。我從來沒有想過。我正在尋找使用Loaders發送進度更新的方式。我會試一試,讓你知道。我認爲你的解決方案應該工作! – douggynix 2014-09-01 10:17:32

+0

該鏈接似乎已經變質。 [這裏](https://yadi.sk/d/qovznXrpUbbum)是一個工作的(我認爲它是相同的)。 – EmmanuelMess 2017-07-25 15:07:15

0

在您實施LoaderManager.LoaderCallback(可能是您的活動)的課程中,您必須覆蓋一個onLoadFinished()方法。這是AsyncTaskLoader完成加載時返回的內容。

+1

我可能會誤,但在裝入AsyncTaskLoader時未調用onLoadFinished?不完全確定如何解決我的問題,但我是'AsyncTaskLoaders'的新手,所以我可能會錯過一些東西。 'onLoadFinished'等價於'AsyncTask'中的'onProgressUpdate'嗎? – 2012-04-16 13:37:08

+0

這相當於'onPostExecute' – 2012-04-16 16:10:41

+2

這不是我要找的。我需要相當於'onProgressUpdate',所以我可以在後臺進程運行時顯示狀態。我不認爲'AsyncTaskLoader'有一個。 – 2012-04-17 00:25:05

1

回答我自己的問題,但從我所知道的來看,如果您需要更新UI,AsyncTaskLoader不是最好的選擇。

4

電解金屬錳......你不應該這樣做。

因爲匿名類如何訪問父類方法或字段是通過存儲對父類的不可見引用。

比如你有一個Activity

public class MyActivity 
    extends Activity 
{ 
    public void someFunction() { /* do some work over here */ } 

    public void someOtherFunction() { 
     Runnable r = new Runnable() { 
      @Override 
      public void run() { 
       while (true) 
        someFunction(); 
      } 
     }; 
     new Thread(r).start(); // use it, for example here just make a thread to run it. 
    } 
} 

編譯器實際上會產生這樣的事情:

private static class AnonymousRunnable { 
    private MyActivity parent; 
    public AnonymousRunnable(MyActivity parent) { 
     this.parent = parent; 
    } 

    @Override 
    public void run() { 
     while (true) 
      parent.someFunction(); 
    } 
} 

所以,當你的父母Activity銷燬(由於配置改變,例如) ,而你的匿名課程仍然存在,整個活動無法進行。 (因爲有人仍然有一個參考。)

這會使內存泄漏並使您的應用程序進入LIMBO!

如果是我,我會實施 「onProgressUpdate()」 像這樣裝載機:

public class MyLoader extends AsyncTaskLoader<Something> { 
    private Observable mObservable = new Observable(); 
    synchronized void addObserver(Observer observer) { 
     mObservable.addObserver(observer); 
    } 
    synchronized void deleteObserver(Observer observer) { 
     mObservable.deleteObserver(observer); 
    } 

    @Override 
    public void loadInBackground(CancellationSignal signal) 
    { 
     for (int i = 0;i < 100;++i) 
      mObservable.notifyObservers(new Integer(i)); 
    } 
} 

而在你Activity

public class MyActivity extends Activity { 
    private Observer mObserver = new Observer() { 
     @Override 
     public void update(Observable observable, Object data) { 
      final Integer progress = (Integer) data; 
      mTextView.post(new Runnable() { 
       mTextView.setText(data.toString()); // update your progress.... 
      }); 
     } 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreated(savedInstanceState); 

     MyLoader loader = (MyLoader) getLoaderManager().initLoader(0, null, this); 
     loader.addObserver(mObserver); 
    } 

    @Override 
    public void onDestroy() { 
     MyLoader loader = (MyLoader) getLoaderManager().getLoader(0); 
     if (loader != null) 
      loader.deleteObserver(mObserver); 
     super.onDestroy(); 
    } 
} 

期間onDestroy()記得deleteObserver()是非常重要的,這樣裝載者就永遠不會參考你的活動。 (在您的Application生命週期中,裝載程序可能會保持活動狀態...)

+1

看來你錯過了Observable上的setChanged(),不是嗎? – Maxr1998 2016-07-08 19:42:15