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