2012-09-03 26 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。 –