如何使用Android使用FutureTask或BackgroundTask实现.get功能?

我正在制作一个机器人库。在我的库中,我想允许用户在后台或主线程中执行分部任务

我想做这样的事情。

第一种情况

MyLibabry.with(context)
     .performSomeTask(<params>)
     .execute();

当用户编写上述代码片段代码时。任务应在后台执行。因此,我将使用任何侦听器返回任务的结果。

现在考虑下面的代码片段。

第二种情况

Result result = MyLibabry.with(context)
     .performSomeTask(<params>)
     .get();

现在,当用户在语句末尾附加 get() 时。该任务应在主线程上执行并阻止其他线程。这就是结果立即初始化的原因。

所以我的问题是,我该如何实现这样的功能,即如果用户附加了.get(),则该线程应该在主线程上运行。否则在后台。performSomeTask()

注意:不要专注于返回结果。我将在Java泛型中实现它。我想知道的是如何使代码可重用,以便当用户仅附加.get()时,它将在主线程上运行。否则,相同的代码应在后台运行。我不想写重复的代码。

您可以引用现有库。

  • AsyncTask - 用于执行后台任务的 Android 官方。
  • ION - 用于下载/上传文件

所以两个库具有相同的功能,还有更多的库做同样的事情,我想做同样的事情。

如果有人能为我提供一个小例子,那就太好了。


答案 1

(我希望,您在上面的示例中通过返回值来澄清)因此,这是针对您的任务的几种类型的单一解决方案。仔细观察在新线程中运行的任务。您需要在后台线程池中启动操作。...

注意!(我也希望你澄清使用背景线程。例如,将上面的代码与函数 .execute() 一起使用 - 不会启动新线程,而只是将新任务从 BlockingQueue 执行到静态 ThreadPool 中)

那么下一步是什么呢?使用函数 .get() 在 MainThread 中执行任务,您需要在当前操作循环中发布此任务。你将帮助处理程序和循环器。回答你的问题,你应该知道,你只有一种方法可以完成这项任务。使用方法 .execute() 在后台线程中启动操作,并使用方法 .get() 向处理程序启动新任务。仅此而已!


如果你想了解一些实现的例子,有很多种解决方案。我只是使用Handler和HandlerThread发布单曲,以低估此示例的工作。

public class MyLibrary extend HandlerThread {

    private static Handler backgroundHandler;
    private static Handler foregroundHandler;
    private static MyLibrary myLibrary

    private MyLibrary () {
        super(MyLibrary.class.getSimpleName());
        start();
    }

    public static MyLibrary getInstance() {
        if (myLibrary == null) {
            synchronized (MyLibrary.class) {
                if (myLibrary == null) {
                    myLibrary = new MyLibrary();
                }
            }
        }
        return myLibrary;
    }

    public static WorkingTask with (Context context) {
         //Just update, if there are null
         if (foregroundHandler == null) {
              foregroundHandler = new Handler(context.getMainLooper);
         }

         if (backgroundHandler == null) {
             backgroundHandler = new Handler(getLooper);
         }
         return new WorkingTask();
    }

    public void getBackgroundHandler () {
        return backgroundHandler;
    }
    public void getForegroundHandler () {
        return foregroundHandler;
    }
 }


  // ..........


public class WorkingTask  {
   private Runnable workingRunnable;

   public performTask (Runnable run) {
       this.workingRunnable = run; 
       return this;
   }

    public void execute () {
       MyLibrary.getInstance().getBackgoundHandler()
          .postRunnable(workingRunnable)
    }

    public void get () {
       MyLibrary.getInstance().getForegroundHanlder()
          .postRunnable(workingRunnable)
    }
}

答案 2

您必须使用未来任务类在后台执行任务。

第一种情况如果任务在后台,则将使用结果接口方法返回。

第二种情况如果任务在前台,则将输出直接返回到调用类。

执行() 的示例代码

public void execute() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Future future = mExecutorService.submit(mCursorBinderTask);
                Log.d("asd", "onCreate: started ");
                while (true) {
                    if (future.isDone()) {
                        if (mResultListener != null) {
                            try {
                                mResultListener.onResult(future.get());
                            } catch (InterruptedException e) {
                                mResultListener.onResult(null);
                            } catch (ExecutionException e) {
                                mResultListener.onResult(null);
                            }
                        }
                        break;
                    }
                }
            }
        }).start();
    }

get() 的示例代码

public ArrayList<T> get() throws ExecutionException, InterruptedException {
        return mCursorBinderTask.call();
    }

推荐