繁体   English   中英

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

[英]Android: How to update an UI from AsyncTask if AsyncTask is in a separate class?

我讨厌内部班级。

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

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

我需要异步任务从主活动更新 textView。

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

但是如何从一个外部的、独立的、异步的任务呢?

更新:这看起来像工作:

在活动中,我将任务称为

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

在构造函数中我

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

其中 debug 是 AsyncTask 的私有字段。

所以 onProgressUpdate 我可以

debug.append(text);

谢谢大家的建议

AsyncTask 总是与Activity分开的类,但我怀疑你的意思是它与你的活动类文件在不同的文件中,所以你不能从活动的内部类中受益。 只需将 Activity 上下文作为参数传递给您的异步任务(即传递给它的构造函数)

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

    WeakReference<Activity> mWeakActivity;

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

 ...

并在需要时使用(记住不要在doInBackground()期间使用),即当您通常调用时

int id = findViewById(...)

在你调用的 AsyncTask 中,即

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

请注意,当doInBackground()正在进行时,我们的Activity可能会消失(因此返回的引用可能变为null ),但是通过使用WeakReference我们不会阻止 GC 收集它(并泄漏内存),并且随着 Activity 消失,它通常毫无意义甚至尝试更新它的状态(仍然,根据您的逻辑,您可能想要执行诸如更改内部状态或更新数据库之类的操作,但必须跳过触摸 UI)。

使用接口 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(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 完成所有任务后调用,并将获得“结果”作为参数,由 doInBackground(){ return "";} 返回。

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

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

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

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

//你的代码在这里}

在 AynckTask 类中调用这个函数。

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

我为这种场景写了一个 AsyncTask 的小扩展。 它允许您将 AsyncTask 保留在单独的类中,但也使您可以方便地访问 Tasks 的完成:

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(...)。

这个问题已经得到了回答,我仍然在发布我猜应该如何做..

主要活动类

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM