简体   繁体   English

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

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

I hate inner class.我讨厌内部班级。

I've a main activity who launches a 'short-life' AsyncTask.我有一个主要活动,它启动了一个“短命”的 AsyncTask。

AsyncTask is in a separate file , is not an inner class of main activity AsyncTask在一个单独的文件中,不是主要活动的内部类

I need async task updates a textView from main Activity.我需要异步任务从主活动更新 textView。

I know i can update a TextView from onProgressUpdate, if AsyncTask is a inner class我知道我可以从 onProgressUpdate 更新 TextView,如果 AsyncTask 是一个内部类

But how from an external, indipendent, async task ?但是如何从一个外部的、独立的、异步的任务呢?

UPDATE: This looks like working :更新:这看起来像工作:

In acitivty i call the task在活动中,我将任务称为

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

In the constructor i've在构造函数中我

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

where debug was a private field of AsyncTask.其中 debug 是 AsyncTask 的私有字段。

So onProgressUpdate I can所以 onProgressUpdate 我可以

debug.append(text);

Thanks for all of you suggestions谢谢大家的建议

AsyncTask is always separate class from Activity , but I suspect you mean it is in different file than your activity class file, so you cannot benefit from being activity's inner class. AsyncTask 总是与Activity分开的类,但我怀疑你的意思是它与你的活动类文件在不同的文件中,所以你不能从活动的内部类中受益。 Simply pass Activity context as argument to your Async Task (ie to its constructor)只需将 Activity 上下文作为参数传递给您的异步任务(即传递给它的构造函数)

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

    WeakReference<Activity> mWeakActivity;

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

 ...

and use when you need it (remember to NOT use in during doInBackground() ) ie so when you would normally call并在需要时使用(记住不要在doInBackground()期间使用),即当您通常调用时

int id = findViewById(...)

in AsyncTask you call ie在你调用的 AsyncTask 中,即

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

Note that our Activity can be gone while doInBackground() is in progress (so the reference returned can become null ), but by using WeakReference we do not prevent GC from collecting it (and leaking memory) and as Activity is gone, it's usually pointless to even try to update it state (still, depending on your logic you may want to do something like changing internal state or update DB, but touching UI must be skipped).请注意,当doInBackground()正在进行时,我们的Activity可能会消失(因此返回的引用可能变为null ),但是通过使用WeakReference我们不会阻止 GC 收集它(并泄漏内存),并且随着 Activity 消失,它通常毫无意义甚至尝试更新它的状态(仍然,根据您的逻辑,您可能想要执行诸如更改内部状态或更新数据库之类的操作,但必须跳过触摸 UI)。

Using Interface 1) Create one Interface使用接口 1) 创建一个接口

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

2) Implements it in your Activity 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) Create constructor in AsyncTask(Activity activity){} Register your Interface in AsyncTask file and call interface method as below. 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);
    }

}

Here, your OnPostExecute will call after all task done by AsyncTask and will get "result" as a parameter, returned by doInBackground(){ return "";}.在这里,您的 OnPostExecute 将在 AsyncTask 完成所有任务后调用,并将获得“结果”作为参数,由 doInBackground(){ return "";} 返回。

While "dataSendToActivity.sendData(result);"而“dataSendToActivity.sendData(result);” it will call activity's overrided method "public void sendData(String str) {}".它将调用活动的重写方法“public void sendData(String str) {}”。

An edge case to remember: Be sure to pass this , ie you current activity's context to AsyncTask and not create another instance of your activity, otherwise your Activity will be destroyed and new one is created.要记住的边缘情况:确保将this传递给AsyncTask ,即您当前活动的上下文,而不是创建活动的另一个实例,否则您的Activity将被销毁并创建新的Activity

Make an static function in your activity class passing context in it to update your text view and then call this function in your AsynkTask class to update.在您的活动类中创建一个静态函数,在其中传递上下文以更新您的文本视图,然后在您的 AsynkTask 类中调用此函数进行更新。

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

//your code here } //你的代码在这里}

In AynckTask class call this function.在 AynckTask 类中调用这个函数。

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

I wrote a small extension to AsyncTask for this kind of scenario.我为这种场景写了一个 AsyncTask 的小扩展。 It allows you to keep your AsyncTask in a separate class, but also gives you convenient access to the Tasks's completion:它允许您将 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);
    }

}

So first you extend ListenableAsyncTask instead of AsyncTask.所以首先你扩展 ListenableAsyncTask 而不是 AsyncTask。 Then in your UI code, make a concrete instance and set listenWith(...).然后在您的 UI 代码中,创建一个具体实例并设置 listenWith(...)。

The Question has already been answered, still im posting how it should be done i guess..这个问题已经得到了回答,我仍然在发布我猜应该如何做..

Mainactivity class主要活动类

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

now in the async class现在在异步类中

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

// place this code inside your activity class and also declare updating textview static // 将此代码放在您的活动类中,并声明更新 textview 静态

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

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

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