Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/179.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android 11中不推荐使用Android AsyncTask API。有哪些替代方案?_Java_Android_Kotlin_Kotlin Coroutines - Fatal编程技术网

Java Android 11中不推荐使用Android AsyncTask API。有哪些替代方案?

Java Android 11中不推荐使用Android AsyncTask API。有哪些替代方案?,java,android,kotlin,kotlin-coroutines,Java,Android,Kotlin,Kotlin Coroutines,谷歌反对Android 11中的Android AsyncTaskAPI,并建议改用java.util.concurrent。您可以检查提交 如果您在Android中使用异步任务维护一个较旧的代码库,那么将来可能需要对其进行更改。我的问题是,使用java.util.concurrent正确替换下面显示的代码段应该是什么。它是活动的静态内部类。我正在寻找能与minSdkVersion 16一起工作的东西 private static class LongRunningTask extends As

谷歌反对Android 11中的Android AsyncTaskAPI,并建议改用
java.util.concurrent
。您可以检查提交

如果您在Android中使用异步任务维护一个较旧的代码库,那么将来可能需要对其进行更改。我的问题是,使用
java.util.concurrent
正确替换下面显示的代码段应该是什么。它是活动的静态内部类。我正在寻找能与
minSdkVersion 16一起工作的东西

private static class LongRunningTask extends AsyncTask<String, Void, MyPojo> {
        private static final String TAG = MyActivity.LongRunningTask.class.getSimpleName();
        private WeakReference<MyActivity> activityReference;

        LongRunningTask(MyActivity context) {
            activityReference = new WeakReference<>(context);
        }

        @Override
        protected MyPojo doInBackground(String... params) {
            // Some long running task
            
        }

        @Override
        protected void onPostExecute(MyPojo data) {

            MyActivity activity = activityReference.get();
            activity.progressBar.setVisibility(View.GONE);
            populateData(activity, data) ;
        }     


    }
私有静态类LongRunningTask扩展了AsyncTask{
私有静态最终字符串标记=MyActivity.LongRunningTask.class.getSimpleName();
私人财富参考活动参考;
LongRunningTask(MyActivity上下文){
activityReference=新的WeakReference(上下文);
}
@凌驾
受保护的MyPojo doInBackground(字符串…参数){
//一些长时间运行的任务
}
@凌驾
受保护的void onPostExecute(MyPojo数据){
MyActivity=activityReference.get();
activity.progressBar.setVisibility(View.GONE);
填充数据(活动、数据);
}     
}
如何传入字符串?像这样:

class LongRunningTask implements Callable<MyPojo> {
    private final String input;

    public LongRunningTask(String input) {
        this.input = input;
    }

    @Override
    public MyPojo call() {
        // Some long running task
        return myPojo;
    }
}

此示例使用了一个单线程池,它对DB编写(或序列化的网络请求)很有好处,但是如果您希望获得DB读取或多个请求的某些内容,可以考虑以下执行器配置:

private static final Executor THREAD_POOL_EXECUTOR =
        new ThreadPoolExecutor(5, 128, 1,
                TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
私有静态最终执行器线程\u池\u执行器=
新的线程池执行器(5128,1,
TimeUnit.SECONDS,新的LinkedBlockingQueue());

谷歌建议使用Java的并发框架或Kotlin协程。但是Rxjava最终拥有了比java并发更大的灵活性和功能,因此获得了相当大的普及。

Android不推荐Android 11中的AsyncTask API,以摆脱一开始的部分问题

那么,现在是什么?
  • 线程
  • 执行者
  • RxJava
  • 可倾听的未来
  • 根据
    AsyncTask
    ,协同程序在API级别30中被弃用,建议使用标准java.util.concurrent或

    使用后者可以非常简单地实现:

  • CoroutineScope
    上创建通用扩展函数:

     fun <R> CoroutineScope.executeAsyncTask(
             onPreExecute: () -> Unit,
             doInBackground: () -> R,
             onPostExecute: (R) -> Unit
     ) = launch {
         onPreExecute() // runs in Main Thread
         val result = withContext(Dispatchers.IO) { 
             doInBackground() // runs in background thread without blocking the Main Thread
         }
         onPostExecute(result) // runs in Main Thread
     } 
    
  • 活动
    片段
    中:

    lifecycleScope.executeAsyncTask(onPreExecute = {
        // ... runs in Main Thread
    }, doInBackground = {
        // ... runs in Worker(Background) Thread
        "Result" // send data to "onPostExecute"
    }, onPostExecute = {
        // runs in Main Thread
        // ... here "it" is the data returned from "doInBackground"
    })
    
要使用
viewModelScope
lifecycleScope
将下一行添加到应用程序的build.gradle文件的依赖项中:

implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$LIFECYCLE_VERSION" // for viewModelScope
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$LIFECYCLE_VERSION" // for lifecycleScope
在编写
final LIFECYCLE\u VERSION=“2.3.0-alpha05”

更新

我们还可以使用
onProgressUpdate
功能实现进度更新:

fun <P, R> CoroutineScope.executeAsyncTask(
        onPreExecute: () -> Unit,
        doInBackground: suspend (suspend (P) -> Unit) -> R,
        onPostExecute: (R) -> Unit,
        onProgressUpdate: (P) -> Unit
) = launch {
    onPreExecute()

    val result = withContext(Dispatchers.IO) {
        doInBackground {
            withContext(Dispatchers.Main) { onProgressUpdate(it) }
        }
    }
    onPostExecute(result)
}

在这里,我使用协程为AsyncTask创建了一个替代方案,该方案可以与AsyncTask一样使用,而无需更改项目中的许多代码库

    ExecutorService executor = Executors.newSingleThreadExecutor();
    Handler handler = new Handler(Looper.getMainLooper());

    executor.execute(() -> {
        //Background work here
        handler.post(() -> {
            //UI Thread work here
        });
    });
  • 创建一个新的抽象类AsyncTaskCorroutine,它接受输入参数和输出参数数据类型。当然,这些参数是可选的:)

  • 如果您需要发送pass参数

      new AsyncTaskCoroutine<Integer, Boolean>() {
    
         @Override
         public Boolean doInBackground(Integer... params) {
             return null;
         }
    
         @Override
         public void onPostExecute(@Nullable Boolean result) {
    
         }
    
         @Override
         public void onPreExecute() {
    
         }
     }.execute();
    
    new AsyncTaskCoroutine(){
    @凌驾
    公共布尔doInBackground(整数…参数){
    返回null;
    }
    @凌驾
    public void onPostExecute(@Nullable Boolean result){
    }
    @凌驾
    公共无效onPreExecute(){
    }
    }.execute();
    
  • 我的自定义替换:

    它仅在应用程序正在运行时(更具体地说是安排任务的活动)起作用,但它能够在后台任务完成后更新UI


    编辑:我的异步任务不再需要活动才能运行。

    最简单的替代方法之一是使用
    线程

    new Thread(new Runnable() {
        @Override
        public void run() {
            // do your stuff
            runOnUiThread(new Runnable() {
                public void run() {
                    // do onPostExecute stuff
                }
            });
        }
    }).start();
    
    如果您的项目支持Java8,那么可以使用lambda

    new Thread(() -> {
            // do background stuff here
            runOnUiThread(()->{
                // OnPostExecute stuff here
            });
        }).start();
    

    您可以使用此自定义类作为AsyncTask的替代方案,这与AsyncTask相同,因此您不需要为相同的任务进行额外的工作

    import android.os.Handler;
    import android.os.Looper;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.SynchronousQueue;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class TaskRunner {
    
        private static final int CORE_THREADS = 3;
        private static final long KEEP_ALIVE_SECONDS = 60L;
        private static TaskRunner taskRunner = null;
        private Handler handler = new Handler(Looper.getMainLooper());
        private ThreadPoolExecutor executor;
    
        private TaskRunner() {
            executor = newThreadPoolExecutor();
        }
    
        public static TaskRunner getInstance() {
            if (taskRunner == null) {
                taskRunner = new TaskRunner();
            }
            return taskRunner;
        }
    
        public void shutdownService() {
            if (executor != null) {
                executor.shutdown();
            }
        }
    
        public void execute(Runnable command) {
            executor.execute(command);
        }
    
        public ExecutorService getExecutor() {
            return executor;
        }
    
        public <R> void executeCallable(@NonNull Callable<R> callable, @NonNull OnCompletedCallback<R> callback) {
            executor.execute(() -> {
                R result = null;
                try {
                    result = callable.call();
                } catch (Exception e) {
                    e.printStackTrace(); // log this exception
                } finally {
                    final R finalResult = result;
                    handler.post(() -> callback.onComplete(finalResult));
                }
            });
        }
    
        private ThreadPoolExecutor newThreadPoolExecutor() {
            return new ThreadPoolExecutor(
                    CORE_THREADS,
                    Integer.MAX_VALUE,
                    KEEP_ALIVE_SECONDS,
                    TimeUnit.SECONDS,
                    new SynchronousQueue<>()
            );
        }
    
        public interface OnCompletedCallback<R> {
            void onComplete(@Nullable R result);
        }
    }
    
    没有lambda表达式

    TaskRunner.getInstance().executeCallable(() -> 1, result -> {
    });
    
    
    TaskRunner.getInstance().execute(() -> {
    });
    
    TaskRunner.getInstance().executeCallable(new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
            return 1;
        }
    }, new TaskRunner.OnCompletedCallback<Integer>() {
        @Override
        public void onComplete(@Nullable Integer result) {
    
        }
    });
    
    TaskRunner.getInstance().execute(new Runnable() {
        @Override
        public void run() {
    
        }
    });
    

    只需用这个线程替换整个类,并将其放入一个传递变量的方法中

    new Thread(() -> {
                // do background stuff here
                runOnUiThread(()->{
                    // OnPostExecute stuff here
                  
                });
            }).start();
    
    在片段中,将上下文添加到
    runOnUiThread()
    methode:

     new Thread(() -> {
                // do background stuff here
                context.runOnUiThread(()->{
                    // OnPostExecute stuff here
                });
            }).start();
    

    您可以直接使用
    java.util.concurrent
    包中的执行器

    我也搜索了一下,在这篇文章中找到了一个解决方案

    不幸的是,这篇文章使用的是Kotlin,但经过一点努力,我已经将其转换为Java。这就是解决方案

        ExecutorService executor = Executors.newSingleThreadExecutor();
        Handler handler = new Handler(Looper.getMainLooper());
    
        executor.execute(new Runnable() {
            @Override
            public void run() {
    
                //Background work here
    
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        //UI Thread work here
                    }
                });
            }
        });
    
    很简单吧?如果您在项目中使用Java8,则可以将其简化一点

        ExecutorService executor = Executors.newSingleThreadExecutor();
        Handler handler = new Handler(Looper.getMainLooper());
    
        executor.execute(() -> {
            //Background work here
            handler.post(() -> {
                //UI Thread work here
            });
        });
    
    尽管如此,它无法在代码简洁性方面击败kotlin,但它比以前的java版本要好


    希望这对你有帮助。谢谢

    使用该类在后台线程中执行后台任务该类适用于包括android 11在内的所有android API版本而且该代码与异步任务doInBackgroundonPostExecute方法相同

    public abstract class BackgroundTask {
    
        private Activity activity;
        public BackgroundTask(Activity activity) {
            this.activity = activity;
        }
    
        private void startBackground() {
            new Thread(new Runnable() {
                public void run() {
    
                    doInBackground();
                    activity.runOnUiThread(new Runnable() {
                        public void run() {
    
                            onPostExecute();
                        }
                    });
                }
            }).start();
        }
        public void execute(){
            startBackground();
        }
    
        public abstract void doInBackground();
        public abstract void onPostExecute();
    
    }
    
    复制上述类后,您可以将其用于:

    new BackgroundTask(MainActivity.this) {
            @Override
            public void doInBackground() {
    
                //put you background code
                //same like doingBackground
                //Background Thread
            }
    
            @Override
            public void onPostExecute() {
    
                //hear is result part same
                //same like post execute
                //UI Thread(update your UI widget)
            }
        }.execute();
    

    HandlerThread可以用作AsyncTask的替代方案。它们是长时间运行的线程。HandlerThread的示例如下:

    您可以创建两个处理程序对象。其中一个将用于将消息从workerThread发送到UI线程

    Handler uiHandler,workerHandler;
    Message msg;
    HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
    handlerThread.start();
    Handler.Callback callback=new Handler.Callback() {
            @Override
            public boolean handleMessage(@NonNull Message msg) {
                // handle messages sent from working thread (like updating UI)...
                return true;
            }
        }
    uiHandler=new Handler(callback);
    workerHandler = new Handler(handlerThread.getLooper());
    workerHandler.post(new Runnable(){
               // Perform required task
               uiHandler.sendMessage(msg); // this message will be sent to and handled by UI Thread
    });
    

    另外,请记住HandlerThreads在活动的生命周期之外运行,因此需要正确清理它们,否则会出现线程泄漏。您可以在活动的onDestroy()中使用quit()或quitsafety()方法来防止线程泄漏。

    您可以根据需要迁移到下一个方法

    • 线程+处理程序
    • 执行人
    • 未来
    • 意向服务
    • TaskRunner.getInstance().executeCallable(new Callable<Integer>() {
          @Override
          public Integer call() throws Exception {
              return 1;
          }
      }, new TaskRunner.OnCompletedCallback<Integer>() {
          @Override
          public void onComplete(@Nullable Integer result) {
      
          }
      });
      
      TaskRunner.getInstance().execute(new Runnable() {
          @Override
          public void run() {
      
          }
      });
      
      TaskRunner.getInstance().shutdownService();
      
      new Thread(() -> {
                  // do background stuff here
                  runOnUiThread(()->{
                      // OnPostExecute stuff here
                    
                  });
              }).start();
      
       new Thread(() -> {
                  // do background stuff here
                  context.runOnUiThread(()->{
                      // OnPostExecute stuff here
                  });
              }).start();
      
          ExecutorService executor = Executors.newSingleThreadExecutor();
          Handler handler = new Handler(Looper.getMainLooper());
      
          executor.execute(new Runnable() {
              @Override
              public void run() {
      
                  //Background work here
      
                  handler.post(new Runnable() {
                      @Override
                      public void run() {
                          //UI Thread work here
                      }
                  });
              }
          });
      
          ExecutorService executor = Executors.newSingleThreadExecutor();
          Handler handler = new Handler(Looper.getMainLooper());
      
          executor.execute(() -> {
              //Background work here
              handler.post(() -> {
                  //UI Thread work here
              });
          });
      
      public abstract class BackgroundTask {
      
          private Activity activity;
          public BackgroundTask(Activity activity) {
              this.activity = activity;
          }
      
          private void startBackground() {
              new Thread(new Runnable() {
                  public void run() {
      
                      doInBackground();
                      activity.runOnUiThread(new Runnable() {
                          public void run() {
      
                              onPostExecute();
                          }
                      });
                  }
              }).start();
          }
          public void execute(){
              startBackground();
          }
      
          public abstract void doInBackground();
          public abstract void onPostExecute();
      
      }
      
      new BackgroundTask(MainActivity.this) {
              @Override
              public void doInBackground() {
      
                  //put you background code
                  //same like doingBackground
                  //Background Thread
              }
      
              @Override
              public void onPostExecute() {
      
                  //hear is result part same
                  //same like post execute
                  //UI Thread(update your UI widget)
              }
          }.execute();
      
      Handler uiHandler,workerHandler;
      Message msg;
      HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
      handlerThread.start();
      Handler.Callback callback=new Handler.Callback() {
              @Override
              public boolean handleMessage(@NonNull Message msg) {
                  // handle messages sent from working thread (like updating UI)...
                  return true;
              }
          }
      uiHandler=new Handler(callback);
      workerHandler = new Handler(handlerThread.getLooper());
      workerHandler.post(new Runnable(){
                 // Perform required task
                 uiHandler.sendMessage(msg); // this message will be sent to and handled by UI Thread
      });