如何使用后台任务/异步任务编写更线性可读的Java代码

huangapple go评论99阅读模式
英文:

How to make linear/more readable Java code with background/asynctask

问题

以下是翻译好的代码部分:

  1. 此刻我有如下代码
  2. public class SomeActivity {
  3. void onCreate() {
  4. doSomething();
  5. if (weNeedToDoSomeAsncTask()) {
  6. new SomeAsyncTask(afterSomeAsyncTask).execute();
  7. } else {
  8. new DifferentAsyncTask(afterAnotherAsyncTask).execute();
  9. }
  10. }
  11. PostExecute afterSomeAsyncTask = new PostExecute() {
  12. void Callback(String response) {
  13. doSomethingElse(response);
  14. new DifferentAsyncTask(afterAnotherAsyncTask).execute();
  15. }
  16. }
  17. }

这个代码在表面上看起来还不错,但我已经大大简化了代码,你可以想象当你有多个调用并且出现一些分支情况时,它会变得多么复杂。

为了帮助理解,实际用例通常是这样的:

  • 使用SDK获取一些设备/用户信息
  • 使用返回的信息进行Web服务身份验证
  • 将一些日志信息发送到Web服务
  • 从Web服务获取一些数据
  • 从Web服务获取一些其他数据
  • 使用这些数据生成UI

我希望我的代码看起来更像这样:

  1. public class SomeActivity {
  2. void onCreate() {
  3. doSomething();
  4. if (weNeedToDoSomeAsncTask()) {
  5. new SomeAsyncTask().execute();
  6. doSomethingElse(response);
  7. }
  8. new DifferentAsyncTask().execute();
  9. afterAnotherAsyncTask();
  10. }
  11. }

我以前尝试过使用.get(),但遇到了问题,但从来没有搞清楚为什么(可能是因为我试图在一个AsyncTask内部调用另一个,我听说这是不推荐的,但那是很久以前,所以不能确定)。虽然我知道.get在某种程度上违反了AsyncTask的初衷,但我之所以使用它,是因为Java强制我这样做(用于网络通信等)。我的应用程序依赖于结果才能继续,直到它返回为止,无法执行其他任何操作。

我应该再试一次.get()技术吗?还是这是一个非常糟糕的主意?

我应该只是接受代码变得更难阅读,然后需要跳转到回调方法以尝试理解代码流程吗?

还是有其他选择?

我也刚刚了解到了一个很不错的库 Needle,看起来像是这样的:

  1. NetworkService networkService = new NetworkService();
  2. Needle.onBackgroundThread().serially().execute(networkService);
  3. String result = doSomethingWithResponse(networkService.response);
  4. AnotherNetworkService anotherNetworkService = new AnotherNetworkService(result);
  5. Needle.onBackgroundThread().serially().execute(anotherNetworkService);

但也许这与AsyncTask.get()方法是一样的?

  1. <details>
  2. <summary>英文:</summary>
  3. At the moment I have something like;

public class SomeActivity {
void onCreate() {
doSomething();
if (weNeedToDoSomeAsncTask()) {
new SomeAsyncTask(afterSomeAsyncTask).execute();
} else {
new DifferentAsyncTask(afterAnotherAsyncTask).execute();
}
}

PostExecute afterSomeAsyncTask = new PostExecute() {
void Callback(String response) {
doSomethingElse(response);
new DifferentAsyncTask(afterAnotherAsyncTask).execute();
}
}
}

  1. This doesn&#39;t look too bad on the face of it, but I have hugely simplified the code and you can imagine how complex it becomes when you have more than a few calls going on and some branching starts to happen.
  2. To help with context, the actual use case is normally something like;
  3. - use an sdk to get some device/user information
  4. - use the returned information to authenticate with a web service
  5. - send some logging info to the web service
  6. - get some data from the web service
  7. - get some other data from the web service
  8. - use that data to generate the UI
  9. I would prefer my code to look a bit more like;

public class SomeActivity {
void onCreate() {
doSomething();
if (weNeedToDoSomeAsncTask()) {
new SomeAsyncTask().execute();
doSomethingElse(response);
}
new DifferentAsyncTask().execute();
afterAnotherAsyncTask();
}
}

  1. I have tried used `.get()` in the past and had issues but never got to the bottom of why (potentially I was trying to call one `AsyncTask` inside another, which I&#39;ve read is a no go- but it was a long time ago so can&#39;t be sure). Whilst I realise `.get` somewhat defeats the object of `AsyncTask`, I am only using it because Java forces me to (for network communication etc). My application is relying on the result to continue and can&#39;t do anything else till it returns anyway.
  2. Should I try the `.get()` technique again? Or is it a really bad idea?
  3. Should I just suck it up and realise the code is harder to read and I will need to jump to the callback methods to try and understand the code flow?
  4. Or is there a different option?
  5. I have also just learnt of Needle which looks like quite a nice library https://zsoltsafrany.github.io/needle/ and I think I could do more like;

NetworkService networkService = new NetworkService();
Needle.onBackgroundThread().serially().execute(networkService);
String result = doSomethingWithResponse(networkService.response);
AnotherNetworkService anotherNetworkService = new AnotherNetworkService(result);
Needle.onBackgroundThread().serially().execute(anotherNetworkService);

  1. But perhaps this is exactly the same as the `AsyncTask.get()` approach?
  2. </details>
  3. # 答案1
  4. **得分**: 1
  5. Kotlin协程。
  6. <details>
  7. <summary>英文:</summary>
  8. The TL;DR of any answer really will be: Kotlin coroutines.
  9. </details>
  10. # 答案2
  11. **得分**: 1
  12. 以下是翻译好的部分:
  13. 看一下[ScheduledThreadPoolExecutor](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html),你可以这样获取它:
  14. ```java
  15. ExecutorService executor = Executors.newScheduledThreadPool(8);

有多种方法用于调度未来的任务。

你的第一个示例可能会像这样:

  1. public class SomeActivity {
  2. void onCreate() {
  3. doSomething();
  4. if (weNeedToDoSomeAsncTask()) {
  5. executor.submit(() -&gt; /* 异步任务 */);
  6. doSomethingElse(response);
  7. }
  8. executor.submit(() -&gt; /* 不同的异步任务 */)
  9. afterAnotherAsyncTask();
  10. }
  11. }

(尽管你需要查看替代阻塞/加入的具体方法。)

英文:

Take a look at ScheduledThreadPoolExecutor which you can obtain like:

  1. ExecutorService executor = Executors.newScheduledThreadPool(8);

There are numerous methods for scheduling futures.

Your first example might look like:

  1. public class SomeActivity {
  2. void onCreate() {
  3. doSomething();
  4. if (weNeedToDoSomeAsncTask()) {
  5. executor.submit(() -&gt; /* async task */);
  6. doSomethingElse(response);
  7. }
  8. executor.submit(() -&gt; /* different async task */)
  9. afterAnotherAsyncTask();
  10. }
  11. }

(Although you'll need to look at the specific methods for alternatives to block/join.)

huangapple
  • 本文由 发表于 2020年7月29日 12:50:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/63146545.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定