1

하나의 구현에 막혔습니다. 나는 타사 SDK (라이브러리)를 통합하고 해당 API를 호출하는 Android 애플리케이션을 개발 중입니다. SDK의 함수 호출은 실제로 응답 (성공 또는 실패)을 제공하는 비동기 호출 (라이브러리에서 호출하는 WebAPI 호출)입니다.Android : 모든 비동기 호출이 완료되면 알립니다.

이제 코드를 통해 상황을 설명하려고합니다.

for (................) { 
    AsyncAPICall (SuccessListener { 
     onSuccess() { 
      for (................) { 
       AsyncAPICall (SuccessListener { 
        onSuccess() { 
         for (................) { 
          AsyncAPICall (SuccessListener, ErrorListener); 
         } 
        } 
       }, ErrorListener); 
      } 
     } 
    }, ErrorListener); 
} 

나는 통지 또는 콜백을 원하거나 모든 비동기 호출이 완료 무언가에 의해 통보. 비동기 호출은 다른 스레드에서 실행되며 for 루프로 인해 많은 호출이 동시에 수행됩니다.

비동기 호출이 응답을 받거나 나 수동으로 뭔가를해야 할 때 알려주는 메커니즘이 있습니까?

어떤 도움이 필요합니까?

답변

0

@Khushbu Shah, 내 대답이 업데이트되었습니다. 조금 변경됩니다 :) (꽤 오래되었습니다.) https://jsonplaceholder.typicode.com/posts/1

private final Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl("https://jsonplaceholder.typicode.com/posts/") 
      .addConverterFactory(GsonConverterFactory.create()) 
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
      .build(); 

    private final RestPostsService restPostsService = retrofit.create(RestPostsService.class); 

    private Observable<Posts> getPostById(int id) { 
     return restPostsService.getPostsById(id); 
    } 

Solution1 :
가 작동하는지 확인하려면, 혼자 예를 들어 작업 및 테스트에이 API를 사용하여 스탠드를 만들어 사용하면 시퀀스에서 호출 여러 작업 이전의 결과 작업은 항상 다음 작업

getPostById(1) 
       .concatMap(posts1 -> { 
        //get post 1 success 
        return getPostById(posts1.getId() + 1); 
       }) 
       .concatMap(posts2 -> { 
        //get post 2 success 
        return getPostById(posts2.getId() + 1); 
       }) 
       .concatMap(posts3 -> { 
        //get post 3success 
        return getPostById(posts3.getId() + 1); 
       }) 
       .subscribeOn(Schedulers.io()) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(finalPosts -> { 
        //get post 4 success 
        Toast.makeText(this, "Final result: " + finalPosts.getId() + " - " + finalPosts.getTitle(), 
          Toast.LENGTH_LONG).show(); 
       }); 

의 입력 Solution2 : 여러 작업을 순서대로 호출 할 때 이전 작업의 모든 결과가 최종 작업의 입력입니다 (예 : 아바타 이미지 및 표지 이미지를 업로드 한 후 api를 호출하여 이러한 이미지 URL로 새 사용자를 생성 한 경우) :

Observable 
       .zip(getPostById(1), getPostById(2), getPostById(3), (posts1, posts2, posts3) -> { 
        //this method defines how to zip all separate results into one 
        return posts1.getId() + posts2.getId() + posts3.getId(); 
       }) 
       .flatMap(finalPostId -> { 
        //after get all first three posts, get the final posts, 
        // the final posts-id is sum of these posts-id 
        return getPostById(finalPostId); 
       }) 
       .subscribeOn(Schedulers.io()) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(finalPosts -> { 
        Toast.makeText(this, "Final posts: " + finalPosts.getId() + " - " + finalPosts.getTitle(), 
          Toast.LENGTH_SHORT).show(); 
       }); 

AndroidManifest를

<uses-permission android:name="android.permission.INTERNET"/> 

루트 build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules. 

buildscript { 
    repositories { 
     jcenter() 
    } 
    dependencies { 
     classpath 'com.android.tools.build:gradle:2.3.3' 
     classpath 'me.tatarka:gradle-retrolambda:3.2.0' 
     classpath 'me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2' 

     // NOTE: Do not place your application dependencies here; they belong 
     // in the individual module build.gradle files 
    } 

    // Exclude the version that the android plugin depends on. 
    configurations.classpath.exclude group: 'com.android.tools.external.lombok' 
} 

allprojects { 
    repositories { 
     jcenter() 
    } 
} 

task clean(type: Delete) { 
    delete rootProject.buildDir 
} 

응용 프로그램/build.gradle

apply plugin: 'me.tatarka.retrolambda' 
apply plugin: 'com.android.application' 

android { 
    compileSdkVersion 26 
    buildToolsVersion "26.0.1" 
    defaultConfig { 
     applicationId "app.com.rxretrofit" 
     minSdkVersion 15 
     targetSdkVersion 26 
     versionCode 1 
     versionName "1.0" 
     testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 
    } 
    buildTypes { 
     release { 
      minifyEnabled false 
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 
     } 
    } 

    compileOptions { 
     sourceCompatibility JavaVersion.VERSION_1_8 
     targetCompatibility JavaVersion.VERSION_1_8 
    } 
} 

dependencies { 
    compile fileTree(dir: 'libs', include: ['*.jar']) 
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 
     exclude group: 'com.android.support', module: 'support-annotations' 
    }) 
    compile 'com.android.support:appcompat-v7:26.+' 
    compile 'com.android.support.constraint:constraint-layout:1.0.2' 
    testCompile 'junit:junit:4.12' 

    provided 'org.projectlombok:lombok:1.16.6' 
    compile 'com.squareup.retrofit2:retrofit:2.3.0' 
    compile 'com.squareup.retrofit2:converter-gson:2.3.0' 
    compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0' 
    compile 'io.reactivex:rxandroid:1.2.1' 
} 

모델

package app.com.rxretrofit; 
import com.google.gson.annotations.SerializedName; 
/** 
* -> Created by Think-Twice-Code-Once on 11/26/2017. 
*/ 
public class Posts { 
    @SerializedName("userId") 
    private int userId; 
    @SerializedName("id") 
    private int id; 
    @SerializedName("title") 
    private String title; 
    @SerializedName("body") 
    private String body; 
    public int getUserId() { 
     return userId; 
    } 
    public void setUserId(int userId) { 
     this.userId = userId; 
    } 
    public int getId() { 
     return id; 
    } 
    public void setId(int id) { 
     this.id = id; 
    } 
    public String getTitle() { 
     return title; 
    } 
    public void setTitle(String title) { 
     this.title = title; 
    } 
    public String getBody() { 
     return body; 
    } 
    public void setBody(String body) { 
     this.body = body; 
    } 
} 

RestPostService.java

package app.com.rxretrofit; 

import retrofit2.http.GET; 
import retrofit2.http.Path; 
import rx.Observable; 

/** 
* -> Created by Think-Twice-Code-Once on 11/26/2017. 
*/ 

public interface RestPostsService { 

    @GET("{id}") 
    Observable<Posts> getPostsById(@Path("id") int id); 
} 
,

덧붙여서 Rx + Retrofit + Dagger + MVP 패턴은 훌륭한 조합입니다.

+1

나는 rxjava가 좋겠지 만 예제는 거의 이해할 수 없다. 예상 zip() observeOn() 및 subscribeOn() 이상 –

+2

Thanks "@ Twink Twise Code Once". 먼저 RxJava를 이해하고 나면이 솔루션을 시도 할 것입니다. –

+0

@TimCastelijns이 대답을주기 전에 Observable.zip()을 살펴 봤지만이 솔루션이 더 간단하다고 생각합니다. –