fossasia / open-event-droidgen

Open Event Android App Generator https://github.com/fossasia/open-event-android/raw/apk/sample-apk-fossasia17-development.apk
GNU General Public License v3.0
2.06k stars 828 forks source link

Refactor MainActivity to isolate components into single responsibility #2152

Open iamareebjamal opened 6 years ago

iamareebjamal commented 6 years ago

Actual Behaviour

MainActivity is handling tons of different business logic tasks...

Expected Behaviour

... that should be distributed over to several single responsibilities components

ParthivMangukiya commented 6 years ago

`public class DownloadHandler {

private static final RealmDataRepository realmDataRepository = RealmDataRepository.getInstance(Realm.getDefaultInstance());

public static Observable<String> downloadAllAssets() {

    return Observable.fromArray(ConstantStrings.EVENT,
            ConstantStrings.SESSIONS,
            ConstantStrings.SPEAKERS,
            ConstantStrings.TRACKS,
            ConstantStrings.SPONSORS,
            ConstantStrings.MICROLOCATIONS,
            ConstantStrings.SESSION_TYPES)
            .flatMapSingle(DownloadHandler::downloadAsset);
}

public static Single<String> downloadAsset(String name) {
    String assetUrl;
    switch (name){
        case ConstantStrings.EVENT:
            assetUrl = Urls.EVENT;
            break;
        case ConstantStrings.SESSIONS:
            assetUrl = Urls.SESSIONS;
            break;
        case ConstantStrings.SPEAKERS:
            assetUrl = Urls.SPEAKERS;
            break;
        case ConstantStrings.TRACKS:
            assetUrl = Urls.TRACKS;
            break;
        case ConstantStrings.SPONSORS:
            assetUrl = Urls.SPONSORS;
            break;
        case ConstantStrings.MICROLOCATIONS:
            assetUrl = Urls.MICROLOCATIONS;
            break;
        case ConstantStrings.SESSION_TYPES:
            assetUrl = Urls.SESSION_TYPES;
            break;
        default:
            return Single.error(new Exception("Invalid Type Argument"));
    }
    return readJsonAsset(name)
            .flatMapCompletable(json -> JsonHandler.handleJsonEvent(name,json))
            .toSingleDefault(assetUrl);
}

private static Single<String> readJsonAsset(final String name) {
    return Single.fromCallable(()->{
        try {
            InputStream inputStream = getAssets().open(name);
            int size = inputStream.available();
            byte[] buffer = new byte[size];
            if (inputStream.read(buffer) == -1)
                Timber.d("Empty Stream");
            inputStream.close();
            return new String(buffer, "UTF-8");
        } catch (IOException ioException) {
            Timber.e("Error on reading event %s from Assets. Exception : %s",name,ioException);
            throw ioException;
        }
    });
}

public static Single<String> downloadFromInternet(String name){
    switch (name){
        case ConstantStrings.EVENT:
            return getEventId()
                    .flatMap((eventId) ->  APIClient.getOpenEventAPI().getEventSingle(eventId))
                    .flatMapCompletable(realmDataRepository::saveEvent)
                    .toSingleDefault(name);
        case ConstantStrings.SESSIONS:
            return APIClient.getOpenEventAPI().getSessionsSingle()
                    .flatMapCompletable(realmDataRepository::saveSessions)
                    .toSingleDefault(name);
        case ConstantStrings.SPEAKERS:
            return APIClient.getOpenEventAPI().getSpeakersSingle()
                    .flatMapCompletable(realmDataRepository::saveSpeakers)
                    .toSingleDefault(name);

        case ConstantStrings.TRACKS:
            return APIClient.getOpenEventAPI().getTracksSingle()
                    .flatMapCompletable(realmDataRepository::saveTracks)
                    .toSingleDefault(name);
        case ConstantStrings.SPONSORS:
            return APIClient.getOpenEventAPI().getSponsorsSingle()
                    .flatMapCompletable(realmDataRepository::saveSponsors)
                    .toSingleDefault(name);
        case ConstantStrings.MICROLOCATIONS:
            return APIClient.getOpenEventAPI().getMicrolocationsSingle()
                    .flatMapCompletable(realmDataRepository::saveLocations)
                    .toSingleDefault(name);
        case ConstantStrings.SESSION_TYPES:
            return APIClient.getOpenEventAPI().getSessionTypesSingle()
                    .flatMapCompletable(realmDataRepository::saveSessionTypes)
                    .toSingleDefault(name);
        default:
            return Single.error(new Exception("Invalid Type Argument"));
    }
}

private static Single<Integer> getEventId(){
    return Single.fromCallable(() -> {
        int eventId = SharedPreferencesUtil.getInt(ConstantStrings.EVENT_ID, 0);
        if(eventId == 0)throw new Exception("error");
        return eventId;
    });
}

private static Observable<String> downloadBatch(){
    return Observable.fromArray(ConstantStrings.EVENT,
            ConstantStrings.SESSIONS,
            ConstantStrings.SPEAKERS,
            ConstantStrings.TRACKS,
            ConstantStrings.SPONSORS,
            ConstantStrings.MICROLOCATIONS,
            ConstantStrings.SESSION_TYPES)
            .flatMapSingle(DownloadHandler::downloadFromInternet);
}

public static Observable<String> downloadAllFromInternet(){
    return downloadFromInternet(ConstantStrings.EVENT)
            .toCompletable()
            .andThen(downloadBatch());
}}`

@iamareebjamal I'm working on this Issue. As I've new to RxJava, I'm not sure whether above code is breaking the chain or not (means downloadAllFromAssets() and downloadAllFromInternet() will run only when subscribes not before And the whole chain will correctly dispose)? Please suggest me any changes?

Because I don't want DownloadHandler depends on any activity, I want to access asset from the application context. Is there any Utils or Strategy exists or Should I need to create one?

I have implemented JsonHandler and I am working DownloadHandler. Because of this event depends on many Fragments, First I want to test it and then I will document my approach and send Incremental PR to each sub Issues.

iamareebjamal commented 6 years ago

Let's discuss this here