繁体   English   中英

如何使用 Runnable 回调替换 AsyncTask onProgressUpdate()

[英]How to replace AsyncTask onProgressUpdate() using Runnable callbacks

我正在尝试在不使用Coroutines或其他库的情况下替换已弃用的AsyncTask ,所以我有

具有以下结构的MyTask对象

public abstract class MyTask<R> implements MyCallable<R> {
    @Override
    public void setUiForLoading() {
       //runs on ui
    }

    @Override
    public void setDataAfterLoading(R result) {
        //runs on ui
    }

    @Override
    public R call() throws Exception {
        //runs in background
        return null;
    }
}

MyCallable只是一个简单的接口

public interface MyCallable<R> extends Callable<R>{
    void setDataAfterLoading(R result);
    void setUiForLoading();
}

并使用这个MyTaskRunner来执行它们

public class MyTaskRunner {

    private final Handler handler = new Handler(Looper.getMainLooper());
    private final Executor executor = Executors.newCachedThreadPool();

    public <R> void executeAsync(MyCallable<R> callable) {
        try {
            callable.setUiForLoading();
            executor.execute(new RunnableTask<R>(handler, callable));
        } catch (Exception e) {
            
        }
    }

    public static class RunnableTask<R> implements Runnable{
        private final Handler handler;
        private final MyCallable<R> callable;

        public RunnableTask(Handler handler, MyCallable<R> callable) {
            this.handler = handler;
            this.callable = callable;
        }

        @Override
        public void run() {
            try {
                final R result = callable.call();
                handler.post(new RunnableTaskForHandler(callable, result));
            } catch (Exception e) {
               
            }
        }
    }

    public static class RunnableTaskForHandler<R> implements Runnable{

        private MyCallable<R> callable;
        private R result;

        public RunnableTaskForHandler(MyCallable<R> callable, R result) {
            this.callable = callable;
            this.result = result;
        }

        @Override
        public void run() {
            callable.setDataAfterLoading(result);
        }
    }
}

它有效,但我不知道如何正确复制AsyncTaskpublishProgress()onProgressUpdate()的行为,这对于显示实际进度而不是不确定的很有用

我不能提供与您相同的代码,但希望您能理解。 一切都是代码本身的自我解释。

import android.app.*;
import android.graphics.*;
import android.os.*;
import android.widget.*;
import java.lang.ref.*;

public class MainActivity extends Activity
{
    private static final class HeavyJob implements Runnable
    {
        private final WeakReference<Handler> handler;
        private final Thread thread;
        private boolean isAlive;
        private boolean state;
        private int progress;

        public final HeavyJob(final Handler handler)
        {
            this.handler = new WeakReference<Handler>(handler);
            thread = new Thread(this);
            isAlive = true;
            thread.setPriority(Thread.NORM_PRIORITY);
            thread.start();
        }

        @Override
        public final void run()
        {
            while(isAlive) {
                try {
                    synchronized(this) {
                        while(!state) this.wait();
                    }
                    Thread.sleep(200L); //Let say this a heavy job which takes 200 m/s each round.
                    progress += 10;
                    final Handler hanRef = handler.get();
                    if(hanRef == null) {
                        isAlive = false;
                        handler.clear();
                        break;
                    }
                    final Message msg = Message.obtain();
                    msg.what = 0;
                    msg.arg1 = progress;
                    hanRef.sendMessageAtTime(msg, SystemClock.uptimeMillis()); //Update its progress each round.
                } catch(final InterruptedException e) {}
            }
            //Finished ???
            final Handler hanRef = handler.get();
            if(hanRef != null) {
                final Message msg = Message.obtain();
                msg.what = 1;
                msg.arg1 = progress; //Make your progress is 100% completed and updated.
                //msg.obj = bitmap;
                hanRef.sendMessageAtTime(msg, SystemClock.uptimeMillis());
            }
        }

        public final synchronized void resume()
        {
            if(isAlive) {
                state = true;
                this.notify();
            }
        }

        public final void suspend()
        {
            state = false;
            thread.interrupt();
        }

        public final void stop()
        {
            isAlive = false; // In case interrupt() does nothing (Thread was not in sleep nor wait mode).
            thread.interrupt();
            handler.clear();
        }
    }

    private static final class UIHandler extends Handler
    {
        private final WeakReference<MainActivity> activity;

        public final UIHandler(final MainActivity activity)
        {
            super(Looper.getMainLooper());
            this.activity = new WeakReference<MainActivity>(activity);
        }

        @Override
        public final void handleMessage(final Message msg)
        {
            final MainActivity referent = activity.get();
            if(referent != null) {
                switch(msg.what) {
                    case 0: referent.onProgress(msg.arg1); break;
                    case 1: referent.onPostExecute(msg.arg1, (Bitmap)msg.obj); break;
                }
            }
        }
    }
    
    private ProgressBar pb;
    private ImageView iv;
    
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        pb = findViewById(R.id.pb);
        iv = findViewById(R.id.next);
        
        UIHandler handler = new UIHandler(this);
        //Initilize the object but will not run yet.
        HeavyJob hj = new HeavyJob(handler);
        
        //Run the job
        hj.resume();
        //Pause the job
        hj.suspend();
        //Resume the job
        hj.resume();
        //Stop the job
        hj.stop();
        
        //Multiple jobs
        for(int i=0; i<10; i++) {
            new HeavyJob(handler);
        }
    }
    
    public final void onProgress(final int progress) {
        pb.setProgress(progress);
    }
    
    public final void onPostExecute(final int progress, Bitmap bitmap)
    {
        pb.setProgress(progress);
        if(bitmap != null) iv.setImageBitmap(bitmap);
    }
    
}

我创建的最好的方法是:

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {

    Button btn_start;
    TextView text;
    ProgressBar progressBar1, progressBar2;
    int num = 0;
    ExecutorService service;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        text = findViewById(R.id.textHello);
        btn_start = findViewById(R.id.btn_start);
        progressBar1 = findViewById(R.id.progressbar1);
        progressBar2 = findViewById(R.id.progressBar2);
        btn_start.setOnClickListener(v -> toDo());

    }

    private void toDo() {
        service = Executors.newSingleThreadExecutor();
        service.execute(() -> {

            runOnUiThread(() -> {
                // onPreExecute method of AsyncTask
                progressBar1.setVisibility(View.VISIBLE);
                progressBar2.setVisibility(View.VISIBLE);

            });

            // doInBackground of AsyncTask
            for (int i = 1; i <= 10000; i++) {
                num = i;
                runOnUiThread(() -> {
                    // onProgressUpdate method of AsyncTask
                    progressUpdate(num);
                });
            }

            runOnUiThread(() -> {
                // onPostExecute method of AsyncTask
                progressBar1.setVisibility(View.GONE);
                progressBar2.setVisibility(View.GONE);
            });

        });

    }

    public void progressUpdate(Integer i) {
        text.setText(String.valueOf(i));
        progressBar2.setProgress(i);
    }

}

暂无
暂无

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

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