2012-09-03 25 views
36

我討厭內心階層。Android:如果AsyncTask位於單獨的類中,如何從AsyncTask更新UI?

我有一個主要的活動,推出一個'短命'AsyncTask。

的AsyncTask是在一個單獨的文件,是不是一個內部類主要活動的

我需要異步更新任務主要活動一個TextView。

我知道我可以更新由onProgressUpdate一個TextView,如果的AsyncTask是一個內部類

但如何從外部,indipendent,異步任務是什麼?

UPDATE:這看起來像工作:

在acitivty我調用任務

backgroundTask = new BackgroundTask(this); 
backgroundTask.execute(); 

在構造函數中,我

public BackgroundTask(Activity myContext) 
{ 
    debug = (TextView) myContext.findViewById(R.id.debugText); 
} 

那裏調試是的AsyncTask的私人領域。

所以onProgressUpdate我可以

debug.append(text); 

感謝大家的建議

+0

你的意思是在另一個班級中,你想訪問UI? –

+0

是的。我需要從AsyncTask更新一個TextView。 – realtebo

+0

您可以在構造函數中傳遞Context並將其轉換爲ActivityClass,您可以使用runOnUIThread方法更改textView。 –

回答

31

編輯我編輯的答案,使用WeakReference


的AsyncTask總是從Activity單獨的類,但我懷疑你的意思是在不同的文件比你的活動類文件,所以你不能從中受益作爲活動的內心階層。簡單地傳遞活動上下文參數傳遞給您的異步任務(即它的構造函數)

class MyAsyncTask extends AsyncTask<URL, Integer, Long> { 

    WeakReference<Activity> mWeakActivity; 

    public MyAsyncTask(Activity activity) { 
     mWeakActivity = new WeakReference<Activity>(activity); 
    } 

... 

,當你需要它(記得在doInBackground()在不使用)使用IE,所以當你通常會調用

int id = findViewById(...) 

中的AsyncTask調用即

Activity activity = mWeakActivity.get(); 
if (activity != null) { 
    int id = activity.findViewById(...); 
} 

注意,我們Activity可以走了,而doInBackground()正在進行中(這樣的參考, nce返回可以變成null),但是通過使用WeakReference我們不會阻止GC收集它(並泄漏內存),並且隨着Activity消失,甚至嘗試更新它的狀態通常是毫無意義的(仍然取決於您可能想要的邏輯做更改內部狀態或更新數據庫等操作,但必須跳過觸摸UI)。

+2

如果你走這條路線,最好把活動參考作爲WeakReference 而不是僅僅是活動。 IMO。 – newbyca

+0

什麼是「WeakReference」? – realtebo

+0

WebnetMobile。好吧,我不確定,很高興知道。 @realtebo,http://developer.android.com/reference/java/lang/ref/WeakReference.html – newbyca

3

只是通過上下文(活動或其他),以您的AsyncTask在構造函數中,然後在的onSuccess或任何你需要onProgressUpdate電話在上下文中。

2

在您的活動類中傳遞一個靜態函數,在其中傳遞上下文以更新您的文本視圖,然後在您的AsynkTask類中調用此函數進行更新。

在活動類: 公共靜態無效updateTextView(){

//你的代碼在這裏 }

在AynckTask類調用這個函數。

+0

完美。謝謝! – hoss

3

我爲這種場景寫了一個AsyncTask的小擴展。它可以讓你保持你的AsyncTask在一個單獨的類,但也讓你方便地訪問任務的完成:

public abstract class ListenableAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result>{ 

    @Override 
    protected final void onPostExecute(Result result) { 
     notifyListenerOnPostExecute(result); 
    } 

    private AsyncTaskListener<Result> mListener; 
    public interface AsyncTaskListener<Result>{ 
     public void onPostExecute(Result result); 
    } 
    public void listenWith(AsyncTaskListener<Result> l){ 
     mListener = l; 
    } 
    private void notifyListenerOnPostExecute(Result result){ 
     if(mListener != null) 
      mListener.onPostExecute(result); 
    } 

} 

所以首先要擴展ListenableAsyncTask代替的AsyncTask。然後在您的UI代碼中,創建一個具體實例並設置listenWith(...)。

2

的問題已經回答了,還是即時發佈應該怎麼做我想..

MainActivity類別

public class MainActivity extends Activity implements OnClickListener 
    { 

     TextView Ctemp; 

     @Override 
     protected void onCreate(Bundle savedInstanceState) 
     { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.activity_main); 
      Ctemp = (TextView) findViewById(R.id.Ctemp); 
      doConv = (Button) findViewById(R.id.doConv); 
      doConv.setOnClickListener(this); 
     } 

     @Override 
     public void onClick(View arg0) // The conversion to do 
     { 
      new asyncConvert(this).execute(); 
     } 
    } 

現在在異步類

public class asyncConvert extends AsyncTask<Void, Void, String> 
{ 
    SoapPrimitive response = null; 
    Context context; 

    public asyncConvert(Context callerclass) 
    { 
     contextGUI = callerclass; 
    } 
. 
. 
. 
. 
protected void onPostExecute(String result) 
    { 
     ((MainActivity) contextGUI).Ctemp.setText(result); // changing TextView 
    } 
} 
1
/** 
    * Background Async Task to Load all product by making HTTP Request 
    * */ 
    public static class updateTExtviewAsyncTask extends AsyncTask<String, String, String> { 

     Context context; 
     ProgressDialog pDialog; 
     String id, name; 

     String state_id; 

     //--- Constructor for getting network id from asking method 

     public updateTExtviewAsyncTask(Context context,String id,String city) 
     { 
      context = context; 
      state_id = id; 
      city_name = city; 
     }  
     /* * 
     * Before starting background thread Show Progress Dialog 
     * */ 
     @Override 
     protected void onPreExecute() 
     { 
      super.onPreExecute(); 
      pDialog = ProgressDialog.show(context, "","Please wait...", true, true); 
      pDialog.show(); 

     } 

     /** 
     * getting All products from url 
     * */ 
     protected String doInBackground(String... args) 
     { 
      return null; 
     } 

     /** 
     * After completing background task Dismiss the progress dialog 
     * **/ 
      protected void onPostExecute(String file_url) { 

        YourClass.UpdateTextViewData("Textview data"); 
     } 
    } 

//地方您的活動類中的代碼,並宣佈更新的TextView靜態

public static void UpdateTextViewData(String tvData) 
{ 
    tv.setText(tvData); 
} 
18

使用界面 1)創建一個接口

public interface OnDataSendToActivity { 
    public void sendData(String str); 
} 

2)實現它在你的活動

public class MainActivity extends Activity implements OnDataSendToActivity{ 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
      new AsyncTest(this).execute(new String[]{"AnyData"}); // start your task 
    } 

    @Override 
    public void sendData(String str) { 
     // TODO Auto-generated method stub 

    } 

} 

3)在AsyncTask中創建構造函數(活動活動){} 在AsyncTask文件中註冊您的接口 和調用接口方法如下。

public class AsyncTest extends AsyncTask<String, Integer, String> { 

    OnDataSendToActivity dataSendToActivity; 
    public AsyncTest(Activity activity){ 
     dataSendToActivity = (OnDataSendToActivity)activity; 
    } 

    @Override 
    protected void onPostExecute(String result) { 
     super.onPostExecute(result); 
     dataSendToActivity.sendData(result); 
    } 

} 

在這裏,您OnPostExecute會的AsyncTask完成所有任務後,打電話會得到「結果」 作爲參數,通過doInBackground返回(){回報「」;}。

雖然「dataSendToActivity.sendData(result);」它會調用活動的overrided方法「public void sendData(String str){}」。

邊緣的情況下要記住:一定要通過this,即你當前活動的上下文AsyncTask而不是創建活動的另一個實例,否則你Activity將被銷燬,新創建一個。

+0

這可能是第一次見面,不能在一個活動中處理多個通用的'AsyncTask'。 – zionpi

+0

這是一個很好的解決方案。實現界面會鬆動耦合,並在此Android Developer視頻中推薦 - https://www.youtube.com/watch?v=jtlRNNhane0&index=4&list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE。 –