英文:
How to make linear/more readable Java code with background/asynctask
问题
以下是翻译好的代码部分:
此刻我有如下代码:
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();
}
}
}
这个代码在表面上看起来还不错,但我已经大大简化了代码,你可以想象当你有多个调用并且出现一些分支情况时,它会变得多么复杂。
为了帮助理解,实际用例通常是这样的:
- 使用SDK获取一些设备/用户信息
- 使用返回的信息进行Web服务身份验证
- 将一些日志信息发送到Web服务
- 从Web服务获取一些数据
- 从Web服务获取一些其他数据
- 使用这些数据生成UI
我希望我的代码看起来更像这样:
public class SomeActivity {
void onCreate() {
doSomething();
if (weNeedToDoSomeAsncTask()) {
new SomeAsyncTask().execute();
doSomethingElse(response);
}
new DifferentAsyncTask().execute();
afterAnotherAsyncTask();
}
}
我以前尝试过使用.get()
,但遇到了问题,但从来没有搞清楚为什么(可能是因为我试图在一个AsyncTask
内部调用另一个,我听说这是不推荐的,但那是很久以前,所以不能确定)。虽然我知道.get
在某种程度上违反了AsyncTask
的初衷,但我之所以使用它,是因为Java强制我这样做(用于网络通信等)。我的应用程序依赖于结果才能继续,直到它返回为止,无法执行其他任何操作。
我应该再试一次.get()
技术吗?还是这是一个非常糟糕的主意?
我应该只是接受代码变得更难阅读,然后需要跳转到回调方法以尝试理解代码流程吗?
还是有其他选择?
我也刚刚了解到了一个很不错的库 Needle,看起来像是这样的:
NetworkService networkService = new NetworkService();
Needle.onBackgroundThread().serially().execute(networkService);
String result = doSomethingWithResponse(networkService.response);
AnotherNetworkService anotherNetworkService = new AnotherNetworkService(result);
Needle.onBackgroundThread().serially().execute(anotherNetworkService);
但也许这与AsyncTask.get()
方法是一样的?
<details>
<summary>英文:</summary>
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();
}
}
}
This doesn'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.
To help with context, the actual use case is normally something like;
- use an sdk to get some device/user information
- use the returned information to authenticate with a web service
- send some logging info to the web service
- get some data from the web service
- get some other data from the web service
- use that data to generate the UI
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();
}
}
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've read is a no go- but it was a long time ago so can'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't do anything else till it returns anyway.
Should I try the `.get()` technique again? Or is it a really bad idea?
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?
Or is there a different option?
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);
But perhaps this is exactly the same as the `AsyncTask.get()` approach?
</details>
# 答案1
**得分**: 1
Kotlin协程。
<details>
<summary>英文:</summary>
The TL;DR of any answer really will be: Kotlin coroutines.
</details>
# 答案2
**得分**: 1
以下是翻译好的部分:
看一下[ScheduledThreadPoolExecutor](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html),你可以这样获取它:
```java
ExecutorService executor = Executors.newScheduledThreadPool(8);
有多种方法用于调度未来的任务。
你的第一个示例可能会像这样:
public class SomeActivity {
void onCreate() {
doSomething();
if (weNeedToDoSomeAsncTask()) {
executor.submit(() -> /* 异步任务 */);
doSomethingElse(response);
}
executor.submit(() -> /* 不同的异步任务 */)
afterAnotherAsyncTask();
}
}
(尽管你需要查看替代阻塞/加入的具体方法。)
英文:
Take a look at ScheduledThreadPoolExecutor which you can obtain like:
ExecutorService executor = Executors.newScheduledThreadPool(8);
There are numerous methods for scheduling futures.
Your first example might look like:
public class SomeActivity {
void onCreate() {
doSomething();
if (weNeedToDoSomeAsncTask()) {
executor.submit(() -> /* async task */);
doSomethingElse(response);
}
executor.submit(() -> /* different async task */)
afterAnotherAsyncTask();
}
}
(Although you'll need to look at the specific methods for alternatives to block/join.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论