Java Android-异步网络调用-响应相互依赖
我今天在开发一个Android应用程序时遇到了这种情况,当时我被要求根据来自两个不同API的响应绘制图形。我在使用截击,我所做的是我进行了一个连续的网络呼叫,即我发出了第一个请求,在该请求的Java Android-异步网络调用-响应相互依赖,java,android,asynchronous,android-volley,sequential,Java,Android,Asynchronous,Android Volley,Sequential,我今天在开发一个Android应用程序时遇到了这种情况,当时我被要求根据来自两个不同API的响应绘制图形。我在使用截击,我所做的是我进行了一个连续的网络呼叫,即我发出了第一个请求,在该请求的onResponse方法中,我发出了第二个请求。然后我在第二次请求的onResponse方法中呈现视图(图形) 现在我想优化这种情况。我想知道一种异步进行这两个网络调用的方法,只有在收到两个API的响应后才能呈现视图。 那么,假设我有3个模块化方法,即- getDataFromServer1(从一台服务器获取
onResponse
方法中,我发出了第二个请求。然后我在第二次请求的onResponse
方法中呈现视图(图形)
现在我想优化这种情况。我想知道一种异步进行这两个网络调用的方法,只有在收到两个API的响应后才能呈现视图。
那么,假设我有3个模块化方法,即-
loadView
(根据从2个网络调用接收的数据渲染图形)我该怎么做呢?有人能解释一下吗?如果两个请求具有相同的数据格式,并且由相同的容器保存。 为什么不简单地检查一下容器的大小呢
public class MainActivity extends AppCompatActivity {
private List<Data> myList = new ArrayList<>();
private boolean error; // if one request got error, another one need to konw,
//use to handle response size 0 or other error
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GsonRequest request1 = new GsonRequest(params... , this.mClazz, null, new Response.Listener() {
@Override
public void onResponse(Object response) {
boolean updateUI = false;
if(myList.size()>0){ //or > the init size
updateUI = true;
}
myList.addAll(response);
if(updateUI){
notifydatasetchange();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
GsonRequest request2 = new GsonRequest(params... , this.mClazz, null, new Response.Listener() {
@Override
public void onResponse(Object response) {
boolean updateUI = false;
if(myList.size()>0){ //or > the init size
updateUI = true;
}
myList.addAll(response);
if(updateUI){
notifydatasetchange();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
}
public类MainActivity扩展了AppCompatActivity{
private List myList=new ArrayList();
private boolean error;//如果一个请求出错,另一个请求需要知道,
//用于处理响应大小0或其他错误
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GsonRequest request1=新的GsonRequest(params…,this.mClazz,null,new Response.Listener()){
@凌驾
公共响应(对象响应){
布尔更新i=false;
如果(myList.size()>0){//或>初始大小
updateUI=true;
}
myList.addAll(响应);
如果(更新){
notifydatasetchange();
}
}
},new Response.ErrorListener(){
@凌驾
公共无效onErrorResponse(截击错误){
}
});
GsonRequest request2=新的GsonRequest(参数…,this.mClazz,null,new Response.Listener()){
@凌驾
公共响应(对象响应){
布尔更新i=false;
如果(myList.size()>0){//或>初始大小
updateUI=true;
}
myList.addAll(响应);
如果(更新){
notifydatasetchange();
}
}
},new Response.ErrorListener(){
@凌驾
公共无效onErrorResponse(截击错误){
}
});
}
}1版-带外部库
这是一个很好的例子,它很方便(或者更一般——任何支持事件驱动编程的框架)
假设我们有以下域类,它们允许我们从web服务获取一些数据: 存储库类:
public class Repository {
protected String name;
public Repository(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
服务接口:
public interface GitService {
List<Repository> fetchRepositories();
}
上面的代码是魔法发生的地方。这是:
- 定义了任务的上下文
- 定义了创建异步线程的必要性
- 定义当硬作业结束时,应在UI线程中处理结果
- 定义了要调用哪些方法来处理结果和错误
在上面的
subscribe
中,我们传递lambda调用以向用户显示结果/错误:
private void showRepositories(List<Repository> repositories) {
// Show repositories in your fragment.
}
private void showErrors() {
// Pops up some contextual information / help.
}
我们将在异步任务中共享此对象
接下来,我们必须实现任务本身,例如:
public class FetchRepositories extends AsyncTask<Void, Void, List<Repository>> {
private AtomicInteger counter;
private GitService service;
public FetchRepositories(AtomicInteger counter, GitService service) {
this.counter = counter;
this.service = service;
}
@Override
protected List<Repository> doInBackground(Void... params) {
return service.fetchRepositories();
}
@Override
protected void onPostExecute(List<Repository> repositories) {
super.onPostExecute(repositories);
int tasksLeft = this.counter.decrementAndGet();
if(tasksLeft <= 0) {
Intent intent = new Intent();
intent.setAction(TASKS_FINISHED_ACTION);
sendBroadcast(intent);
}
}
}
您必须更新视图,而不是记录消息
提到的常量任务\u已完成\u操作
命名您的筛选器:
private static final String TASKS_FINISHED_ACTION = "some.intent.filter.TASKS_FINISHED";
记住在您的活动和清单中初始化并注册接收器和过滤器
活动:
private BroadcastReceiver receiver = new FetchBroadcastReceiver();
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction(TASKS_FINISHED_ACTION);
registerReceiver(receiver, filter);
}
清单(应用程序标记内部):
请记住在onPause()方法中注销接收器
准备好活动后,您可以在某处执行任务(例如,在onCreate
方法中,如第一个示例中所示):
正如您所注意到的,并行任务将仅在Honeycomb和更高版本上运行。
在此版本之前,Android线程池最多可以容纳1个任务
至少我们使用了一些依赖注入和策略模式 @tommus解决方案是最好的方法
如果您想使用简单或更少代码的方法,可以使用布尔标志来确保这两种方法都已执行,并根据条件向前移动
声明将用作标志的易失性布尔变量
private volatile boolean flag = false;
标志在开始时为false。现在,调用两个Web服务。执行的任何服务都会将此标志变为TRUE
getDataFromServer1();
function void onCompleteServer1() {
if(flag) {
loadViews();
} else {
flag = true;
}
}
getDataFromServer2();
onCompleteServer2Request() {
if(flag) {
loadViews();
} else {
flag = true;
}
}
不完美,但我希望这个逻辑对你有用
onDatafromServer1Fetched{
flag1 = true;
}
onDataFromServer2Fetched{
flag2=true;
}
main(){
boolean flag1 = false;
boolean flag2 =false;
getDataFromSerVer1();
getDataFromServer2();
while(!flag1 && !flag2){/**no code required here*/}
loadView();
}
回答得很好。尽管我认为,AndroidObservable
有点过于复杂了——我认为对于RxJava新手来说,从简单的Observable
另一个添加开始会更容易——正如谷歌最近宣布的那样,lambdas将得到新的Jack编译器的支持。所以,在(希望)不远的将来,你将不需要Retrolambda。@DmitryZaitsev-也许,但我认为-最终-AndroidObservable
简化了一切。使用简单的Observable
强制用户记住使用runOnUiThread
方法等处理结果。在学习RxAndroid上投入一些时间可以很快获得回报。很高兴听到很快就推出了对lambdas的支持。不是真的,在你的例子中,AndroidObservable所做的就是在onDestroy
中取消对源代码的订阅。您已经在观察AndroidSchedulers上的值。不需要使用mainThread()
-runOnUiThread
。此外,我发现它太依赖于活动-如果您使用类似MVP的东西,这可能会成为一个问题。@tommus-谢谢您对这个库的详细解释。但就像Dmitry提到的RxJ一样
public class FetchBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("onReceive", "All tasks has been finished.");
// No need to test
// if intent.getAction().equals(TASKS_FINISHED_ACTION) {}
// as we used filter.
}
}
private static final String TASKS_FINISHED_ACTION = "some.intent.filter.TASKS_FINISHED";
private BroadcastReceiver receiver = new FetchBroadcastReceiver();
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction(TASKS_FINISHED_ACTION);
registerReceiver(receiver, filter);
}
<receiver android:name=".TestActivity$FetchBroadcastReceiver"/>
<action android:name="some.intent.filter.TASKS_FINISHED"/>
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
new FetchRepositories(counter, new GithubService())
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new FetchRepositories(counter, new BitbucketService())
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
// Below Honeycomb there was no parallel tasks.
new FetchRepositories(counter, new GithubService()).execute();
new FetchRepositories(counter, new BitbucketService()).execute();
}
private volatile boolean flag = false;
getDataFromServer1();
function void onCompleteServer1() {
if(flag) {
loadViews();
} else {
flag = true;
}
}
getDataFromServer2();
onCompleteServer2Request() {
if(flag) {
loadViews();
} else {
flag = true;
}
}
onDatafromServer1Fetched{
flag1 = true;
}
onDataFromServer2Fetched{
flag2=true;
}
main(){
boolean flag1 = false;
boolean flag2 =false;
getDataFromSerVer1();
getDataFromServer2();
while(!flag1 && !flag2){/**no code required here*/}
loadView();
}