Forked from wispborne/ObservableActivityForResult.java
Created
October 3, 2020 15:13
-
-
Save whileloop99/20e16f96b55d4206e5635741b96d43fb to your computer and use it in GitHub Desktop.
RxJava wrapper for startActivityForResult and onActivityResult flow. Don't break the chain!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import android.content.Context; | |
| import android.content.Intent; | |
| import android.os.Bundle; | |
| import android.support.annotation.NonNull; | |
| import android.support.annotation.Nullable; | |
| import android.support.v7.app.AppCompatActivity; | |
| import com.mywebgrocer.util.ActivityResultData; | |
| import java.util.Random; | |
| import rx.Single; | |
| import rx.subjects.PublishSubject; | |
| /** | |
| * Wraps an activity that is launched for a result (`startActivityForResult`), exposing it as an observable. | |
| * THIS CLASS IS NOT THREAD-SAFE. | |
| * | |
| * @author David Whitman on Apr 28, 2017. | |
| */ | |
| public class ObservableActivityForResult extends AppCompatActivity { | |
| private static int REQUEST_CODE = -1; | |
| private static final String EXTRA_INTENT_TO_LAUNCH = "EXTRA_INTENT_TO_LAUNCH"; | |
| private static PublishSubject<ActivityResultData> resultSubject; | |
| @Override | |
| protected void onCreate(@Nullable Bundle savedInstanceState) { | |
| super.onCreate(savedInstanceState); | |
| startActivityForResult(getIntent().getParcelableExtra(EXTRA_INTENT_TO_LAUNCH), REQUEST_CODE); | |
| } | |
| /** | |
| * Convenience method to create an instance of this class and launch the activity. | |
| * Emits a result based on the result of the activity, then finishes. | |
| * Should never call `onError`. | |
| * Do not call this method in parallel, it will make bad things happen. | |
| */ | |
| public static Single<ActivityResultData> startActivityForResult(@NonNull Context context, @NonNull Intent intentToLaunch) { | |
| // Use Single.create so that resultSubject isn't assigned until the Single is subscribed to. | |
| // Otherwise, this would not work properly if the user wanted to chain two calls | |
| // because the resultSubject wouldn't get reinstantiated when the second Single was subscribed to. | |
| return Single.create(s -> { | |
| // Use random int for each call so a previous result can't somehow intrude on a subsequent one | |
| REQUEST_CODE = new Random().nextInt(32767); // Can only use lower 16 bits for request code | |
| resultSubject = PublishSubject.create(); | |
| final Intent intent = new Intent(context, ObservableActivityForResult.class); | |
| intent.putExtra(EXTRA_INTENT_TO_LAUNCH, intentToLaunch); | |
| context.startActivity(intent); | |
| resultSubject.toSingle().subscribe(s); | |
| }); | |
| } | |
| @Override | |
| protected void onActivityResult(int requestCode, int resultCode, Intent data) { | |
| if (requestCode == REQUEST_CODE) { | |
| resultSubject.onNext(new ActivityResultData(requestCode, resultCode, data)); | |
| resultSubject.onCompleted(); | |
| finish(); | |
| } else { | |
| super.onActivityResult(requestCode, resultCode, data); | |
| } | |
| } | |
| @Override | |
| protected void onDestroy() { | |
| super.onDestroy(); | |
| if (!resultSubject.hasCompleted()) { | |
| resultSubject.onCompleted(); | |
| } | |
| resultSubject = null; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment