Android:如果AsyncTask在一个单独的类中,如何从AsyncTask更新UI?

我讨厌内心阶层。

我有一个主要的活动,启动一个“短命”的AsyncTask。

AsyncTask 在一个单独的文件中 ,不是主要活动的内部类

我需要asynchronous任务更新主Activity的textView。

我知道我可以从onProgressUpdate更新TextView,如果AsyncTask是一个内部类

但是,如何从一个外部的,独立的,asynchronous的任务?

更新:这看起来像工作:

在活跃我呼吁任务

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

在我的构造函数中

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

其中debugging是一个AsyncTask的私人领域。

所以onProgressUpdate我可以

 debug.append(text); 

感谢您的所有build议

编辑我编辑了使用WeakReference的答案


AsyncTask总是与Activity分开的类,但是我怀疑你的意思是它和你的活动类文件在不同的文件中,所以你不能从活动的内部类中受益。 只需将Activity上下文作为parameter passing给Async Task(即构造函数)

 class MyAsyncTask extends AsyncTask<URL, Integer, Long> { WeakReference<Activity> mWeakActivity; public MyAsyncTask(Activity activity) { mWeakActivity = new WeakReference<Activity>(activity); } ... 

并在需要的时候使用(请记住在doInBackground()期间不要使用),也就是说,当你通常要调用的时候

 int id = findViewById(...) 

在你调用ie的AsyncTask中

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

请注意,当doInBackground()正在进行时,我们的Activity可能会消失(所以返回的引用可能会变为null ),但是通过使用WeakReference我们不会阻止GC收集它(并且泄漏内存),并且当Activity消失时,通常是没有意义的甚至尝试更新它的状态(仍然,根据你的逻辑,你可能想要做一些改变内部状态或更新数据库,但触摸UI必须跳过)。

使用接口1)创build一个接口

 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中创build构造函数(Activity activity){}在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完成所有的任务之后调用,并且将得到“result”作为参数,由doInBackground(){return“”;}返回。

而“dataSendToActivity.sendData(result);” 它会调用活动的overrided方法“public void sendData(String str){}”。

需要记住的边缘情况:确保将当前活动的上下文传递给AsyncTask而不是创build另一个活动实例,否则您的Activity将被销毁并创build新的Activity

只需将上下文(活动或其他)传递给构造函数中的AsyncTask,然后在onSuccess或onProgressUpdate上调用任何您需要的上下文。

我为这种场景写了一个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代码中,创build一个具体的实例并设置listenWith(…)。

在您的活动类中创build一个静态函数,在其中传递上下文以更新文本视图,然后在您的AsynkTask类中调用此函数进行更新。

在Activity类中:public static void updateTextView(){

//你的代码在这里}

在AynckTask类中调用这个函数。

这个问题已经被回答,仍然im发布如何应该做我猜..

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(); } } 

现在在asynchronous类

 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 } } 
  /** * 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 static

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