oliveiradev / RxPhoto

This lib using reactive approach for get and take pictures
MIT License
41 stars 14 forks source link

Rxjava2 #7

Open badboy-tian opened 7 years ago

badboy-tian commented 7 years ago

suit for rxjava2

oliveiradev commented 7 years ago

Hi @tianqiujie , a long time I don't work on this lib, I can try switch to Rx2, but I appretiate all help.

badboy-tian commented 7 years ago

I have finished it;

package com.i7play.rsapp.view.rxphoto;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.util.Pair;
import com.i7play.rsapp.view.rxphoto.shared.RxPhotoConstants;
import com.i7play.rsapp.view.rxphoto.util.Utils;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.BiFunction;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import static com.i7play.rsapp.view.rxphoto.shared.RxPhotoConstants.ResponseType.BITMAP;
import static com.i7play.rsapp.view.rxphoto.shared.RxPhotoConstants.ResponseType.THUMB;
import static com.i7play.rsapp.view.rxphoto.shared.RxPhotoConstants.ResponseType.URI;

/**
 * Created by Administrator on 2017/7/14.
 */

public class RxPhoto {
    private static Context context;
    private static PublishSubject<Bitmap> bitmapPublishSubject = PublishSubject.create();
    private static PublishSubject<Uri> uriPublishSubject = PublishSubject.create();
    private static Pair<Integer, Integer>[] sizes;
    private static Pair<Integer, Integer> bitmapSizes;
    private static RxPhotoConstants.ResponseType response;

    private RxPhoto() {
    }

    public static Observable<Bitmap> requestBitmap(Context context, RxPhotoConstants.TypeRequest typeRequest) {
        return requestBitmap(context, typeRequest, new Pair<>(RxPhotoConstants.IMAGE_SIZE, RxPhotoConstants.IMAGE_SIZE));
    }

    public static Observable<Bitmap> requestBitmap(Context context, RxPhotoConstants.TypeRequest typeRequest, Integer width, Integer height) {
        return requestBitmap(context, typeRequest, new Pair<>(width, height));
    }

    public static Observable<Bitmap> requestBitmap(Context context, RxPhotoConstants.TypeRequest typeRequest, Pair<Integer, Integer> bitmapSize) {
        RxPhoto.context = context;
        response = BITMAP;
        startOverlapActivity(typeRequest);
        RxPhoto.bitmapSizes = bitmapSize;
        return bitmapPublishSubject;
    }

    public static Observable<Uri> requestUri(Context context, RxPhotoConstants.TypeRequest typeRequest) {
        RxPhoto.context = context;
        response = URI;
        startOverlapActivity(typeRequest);
        return uriPublishSubject;
    }

    public static Observable<Bitmap> requestThumbnails(Context context, RxPhotoConstants.TypeRequest typeRequest, Pair<Integer, Integer>... sizes) {
        RxPhoto.context = context;
        startOverlapActivity(typeRequest);
        response = THUMB;
        RxPhoto.sizes = sizes;
        return bitmapPublishSubject;
    }

    public static Function<Bitmap, Observable<Bitmap>> transformToThumbnail(final Pair<Integer, Integer>... sizes) {
        return new Function<Bitmap, Observable<Bitmap>>() {
            @Override public Observable<Bitmap> apply(@NonNull final Bitmap bitmap) throws Exception {
                return Observable.fromArray(sizes).flatMap(new Function<Pair<Integer, Integer>, ObservableSource<Bitmap>>() {

                    @Override public ObservableSource<Bitmap> apply(@NonNull Pair<Integer, Integer> size) throws Exception {
                        return Observable.just(getThumbnail(bitmap, size));
                    }
                });
            }
        };
    }

    private static void startOverlapActivity(RxPhotoConstants.TypeRequest typeRequest) {
        Intent intent = new Intent(context, OverlapActivity.class);
        intent.putExtra(RxPhotoConstants.REQUEST_TYPE_EXTRA, typeRequest);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }

    private static Bitmap getBitmapFromStream(Uri url) throws IOException {
        //return MediaStore.Images.Media.getBitmap(context.getContentResolver(), url);
        return Utils.getBitmap(context, url, RxPhoto.bitmapSizes.first, RxPhoto.bitmapSizes.second);
    }

    private static Bitmap getThumbnail(Bitmap bitmap, Pair<Integer, Integer> resizeValues) {
        return ThumbnailUtils.extractThumbnail(bitmap,
            resizeValues.first, resizeValues.second);
    }

    protected static void onActivityResult(Uri uri) {
        if (uri != null) {
            propagateResult(uri);
        }
    }

    private static void propagateResult(Uri uri) {
        try {
            switch (response) {
                case BITMAP:
                    propagateBitmap(uri);
                    break;
                case URI:
                    propagateUri(uri);
                    break;
                case THUMB:
                    propagateThumbs(uri);
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            uriPublishSubject.onError(e);
        }
    }

    private static void propagateUri(Uri uri) {
        uriPublishSubject.onNext(uri);
    }

    private static void propagateBitmap(final Uri uri) {
        getBitmapObservable(uri)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(bitmapPublishSubject);
    }

    private static Observable getBitmapObservable(final Uri uri) {
        /*return Observable.create(new Observable.OnSubscribe<Bitmap>() {
            @Override
            public void call(Subscriber<? super Bitmap> subscriber) {
                try {
                    Bitmap b = getBitmapFromStream(uri);
                    if (b == null)
                        throw new RuntimeException("bitmap is null");
                    subscriber.onNext(b);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }).retryWhen(getRetryHandler());*/
        return Observable.create(new ObservableOnSubscribe<Bitmap>() {

            @Override public void subscribe(ObservableEmitter<Bitmap> e) throws Exception {
                try {
                    Bitmap b = getBitmapFromStream(uri);
                    if (b == null) {
                        throw new RuntimeException("bitmap is null");
                    }
                    e.onNext(b);
                } catch (IOException ee) {
                    throw new RuntimeException(ee);
                }
            }
        }).retryWhen(getRetryHandler());
    }

    private static void propagateThumbs(Uri uri) throws IOException {
        Observable.combineLatest(getBitmapObservable(uri), Observable.fromArray(sizes), new BiFunction<Bitmap, Pair<Integer, Integer>, Bitmap>() {

            @Override public Bitmap apply(@NonNull Bitmap bitmap, @NonNull Pair<Integer, Integer> size) throws Exception {
                return getThumbnail(bitmap, size);
            }
        }).subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(bitmapPublishSubject);
    }

    public static Function<? super Observable<? extends Throwable>, ? extends Observable<?>> getRetryHandler() {
        return new Function<Observable<? extends Throwable>, Observable<?>>() {
            @Override public Observable<?> apply(@NonNull Observable<? extends Throwable> observable) throws Exception {
                return observable.zipWith(Observable.range(1, 5), new BiFunction<Throwable, Integer, Integer>() {

                    @Override public Integer apply(@NonNull Throwable throwable, @NonNull Integer integer) throws Exception {
                        return integer;
                    }
                }).flatMap(new Function<Integer, ObservableSource<?>>() {
                    @Override public ObservableSource<?> apply(@NonNull Integer integer) throws Exception {
                        return Observable.timer(500, TimeUnit.MILLISECONDS);
                    }
                });
            }
        };
    }
}