2014-12-11 137 views
1

我需要從runnable更新ui。我的邏輯如下。 我從片段生命週期的onCreate開始運行。可運行實例負責請求網絡。問題是我不知道在可運行實例從網絡獲取數據後如何更新片段。如何從Runnable更新UI?

開始在CustomFragment.java的片段中運行的代碼。

public void onCreate(Bundle savedInstanceState) { 
    Log.d(DEBUG_TAG, "onCreate"); 
    super.onCreate(savedInstanceState); 

    accountMgr.requestAccountInfo(); 

} 

代碼在AccountManager.java

/** 
* request Account info from server 
*/ 
@TargetApi(Build.VERSION_CODES.HONEYCOMB) 
public void requestAccountInfo() { 
    Account act = getCurrentAccount(); 
    Thread t = new Thread(new RequestAccountInfoTask(act)); 
    t.start(); 
} 

/** 
* automatically update Account info, like space usage, total space size, from background. 
*/ 
class RequestAccountInfoTask implements Runnable { 

    private Account account; 

    public RequestAccountInfoTask(Account account) { 
     this.account = account; 
    } 

    @Override 
    public void run() { 
     doRequestAccountInfo(account); 

    } 
} 

回答

3

runOnUiThread()要求Activity參考。有替代品。您不需要Activity參考您的Thread。你總是可以通過主循環獲取UI處理程序。傳遞其他參數,比如你的接口,在完成任務後更新片段。您在實例化Handler運行

class RequestAccountInfoTask implements Runnable { 

    private Account account; 
    private Handler mHandler; 
    public RequestAccountInfoTask(Account account) { 
     this.account = account; 
     mHandler = new Handler(Looper.getMainLooper()); 
    } 

    @Override 
    public void run() { 
     doRequestAccountInfo(account); 
     //use the handler 
    } 
} 

任何將在UI線程。

當然,使用runOnUiThread()是完全合理的。

+0

我已經實現了這個評論,一些參考[here](http://stackoverflow.com/a/13954718/3962551) – 2014-12-11 05:45:54

1

你不能從運行的更新UI開始運行的。您需要更新UI的處理程序。有關更多信息,請參閱this

+0

這個例子馬上谷歌自己的網頁是一個可運行的調用UIThread。 https://developer.android.com/guide/components/processes-and-threads.html – 2017-02-20 19:45:11

2

請看一看的AsyncTask從一個線程更新UI:

http://developer.android.com/reference/android/os/AsyncTask.html

這裏是從上面的鏈接亮點:

類概述的AsyncTask使正確,方便使用的UI線程。 該類允許執行後臺操作並在UI線程上發佈結果 ,而無需操作線程和/或處理程序。

AsyncTask被設計成圍繞線程和處理程序 的助手類,並不構成通用線程框架。 AsyncTasks 理想情況下應該用於短操作(大部分爲 )。如果您需要保持長時間運行線程, 強烈建議您使用java.util提供的各種API。併發包如Executor,ThreadPoolExecutor和FutureTask。

異步任務由運行在 後臺線程上的計算定義,其結果在UI線程上發佈。異步任務由3個通用類型定義,分別稱爲Params, Progress和Result,以及4個步驟,分別稱爲onPreExecute,doInBackground, onProgressUpdate和onPostExecute。

0

UI只能由創建它的線程修改。在大多數情況下,通過UI線程。所以你需要使用runOnUiThread方法更新。好運

0

我知道這有點不同的答案。但是我希望你看到Android Annotations。哪些非常容易使用。我僅將它們用於背景和Ui線程。通過在您的方法名稱上編寫@Background來執行後臺線程中的所有任務。並在UI線程中完成所有UI更新。我建議你只檢查一次。 http://androidannotations.org/ 謝謝 只要你的答案是關注。你無法從runnable更新你的UI。查看更新你的UI的asyn任務。

1

您可以使用runOnUIThread活動方法。

這裏的代碼可以幫助你:

class RequestAccountInfoTask implements Runnable { 

    private Account account; 

    public RequestAccountInfoTask(Account account) { 
     this.account = account; 
    } 

    @Override 
    public void run() { 
     doRequestAccountInfo(account); 
     if (getActivity() != null) { 
      getActivity().runOnUiThread(new Runnable() { 

       @Override 
       public void run() { 
        // you can update fragment UI at here 
       } 
      }); 
     } 
    } 
} 
0

我建議使用AsynTask或者你可以試試這個

getActivity().runOnUiThread(new Runnable() { 

       @Override 
       public void run() { 
        Toast.makeText(getActivity(), "ON UI Thread", Toast.LENGTH_LONG).show(); 
       } 
      }); 
0

您可以使用事件總線來做到這一點 - http://square.github.io/otto/ 這是很簡單。剛剛從你的線程發送事件,當你需要更新這樣的UI:

... 
//in the end of your heavy job: 
bus.post(new YourEvent()); 

,並在你的活動創建方法:順便說

@Subscribe 
public void onYourEvent(YourEvent event) { 
    //do what you want there 
} 

,您可以通過事件傳遞的任何數據,它是你的自定義課程!請閱讀手冊如何設置此庫,註冊總線活動。這是非常有用和易於使用的

0

您可以創建一個Runnable,然後發佈到主線程。從Processes and Threads

谷歌的開發者頁面這個實現是線程安全的:在後臺操作是由一個單獨的線程中完成 而ImageView的總是從 UI線程操作。

public void onClick(View v) { 
    new Thread(new Runnable() { 
     public void run() { 
      // a potentially time consuming task 
      final Bitmap bitmap = 
        processBitMap("image.png"); 
      mImageView.post(new Runnable() { 
       public void run() { 
        mImageView.setImageBitmap(bitmap); 
       } 
      }); 
     } 
    }).start(); 
}