com.schedjoules.eventdiscovery.framework.microfragments.eventdetails.EventDetailLoaderMicroFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.schedjoules.eventdiscovery.framework.microfragments.eventdetails.EventDetailLoaderMicroFragment.java

Source

/*
 * Copyright 2017 SchedJoules
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.schedjoules.eventdiscovery.framework.microfragments.eventdetails;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.os.Parcel;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;

import com.schedjoules.client.eventsdiscovery.Event;
import com.schedjoules.eventdiscovery.R;
import com.schedjoules.eventdiscovery.databinding.SchedjoulesFragmentEventDetailsContentLoadingActionsBinding;
import com.schedjoules.eventdiscovery.framework.common.BaseFragment;
import com.schedjoules.eventdiscovery.framework.microfragments.eventdetails.fragments.views.EventHeaderView;
import com.schedjoules.eventdiscovery.framework.serialization.boxes.EventBox;
import com.schedjoules.eventdiscovery.framework.serialization.core.Box;
import com.schedjoules.eventdiscovery.framework.services.ActionService;
import com.schedjoules.eventdiscovery.framework.services.EventService;
import com.schedjoules.eventdiscovery.framework.utils.ServiceJob;
import com.schedjoules.eventdiscovery.framework.utils.ServiceJobQueue;
import com.schedjoules.eventdiscovery.framework.utils.SimpleServiceJobQueue;
import com.schedjoules.eventdiscovery.framework.utils.anims.Revealed;
import com.schedjoules.eventdiscovery.framework.widgets.AccentColoredProgressBar;

import org.dmfs.android.microfragments.FragmentEnvironment;
import org.dmfs.android.microfragments.MicroFragment;
import org.dmfs.android.microfragments.MicroFragmentHost;
import org.dmfs.android.microfragments.Timestamp;
import org.dmfs.android.microfragments.timestamps.UiTimestamp;
import org.dmfs.android.microfragments.transitions.ForwardTransition;
import org.dmfs.android.microfragments.transitions.FragmentTransition;
import org.dmfs.httpessentials.exceptions.ProtocolError;
import org.dmfs.httpessentials.exceptions.ProtocolException;
import org.dmfs.httpessentials.types.Link;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * {@link MicroFragment} which loads the necessary extra data to show the event details screen.
 * <p>
 * It already receives an event with the basic information, so it can show them while loading the rest (rest is event description and actions).
 *
 * @author Gabor Keszthelyi
 */
public final class EventDetailLoaderMicroFragment implements MicroFragment<Event> {
    public final static Creator<EventDetailLoaderMicroFragment> CREATOR = new Creator<EventDetailLoaderMicroFragment>() {
        @Override
        public EventDetailLoaderMicroFragment createFromParcel(Parcel source) {
            Box<Event> eventBox = source.readParcelable(getClass().getClassLoader());
            return new EventDetailLoaderMicroFragment(eventBox.content());
        }

        @Override
        public EventDetailLoaderMicroFragment[] newArray(int size) {
            return new EventDetailLoaderMicroFragment[size];
        }
    };
    private final Event mEvent;

    public EventDetailLoaderMicroFragment(Event event) {
        mEvent = event;
    }

    @NonNull
    @Override
    public String title(@NonNull Context context) {
        throw new RuntimeException("This Fragment has no title");
    }

    @NonNull
    @Override
    public Fragment fragment(@NonNull Context context, MicroFragmentHost host) {
        return new LoaderFragment();
    }

    @NonNull
    @Override
    public Event parameter() {
        return mEvent;
    }

    @Override
    public boolean skipOnBack() {
        return true;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeParcelable(new EventBox(mEvent), flags);
    }

    public final static class LoaderFragment extends BaseFragment {
        private final Timestamp mTimestamp = new UiTimestamp();
        private ServiceJobQueue<ActionService> mActionServiceJobQueue;
        private ServiceJobQueue<EventService> mEventServiceJobQueue;

        private Event mEvent;

        private AtomicReference<Event> mEventWithDetails = new AtomicReference<>();
        private AtomicReference<List<Link>> mActions = new AtomicReference<>();
        private AtomicBoolean mSleepIsOver = new AtomicBoolean();
        private AccentColoredProgressBar mProgressBar;

        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mActionServiceJobQueue = new SimpleServiceJobQueue<>(new ActionService.FutureConnection(getActivity()));
            mEventServiceJobQueue = new SimpleServiceJobQueue<>(new EventService.FutureConnection(getActivity()));
            mEvent = new FragmentEnvironment<Event>(this).microFragment().parameter();
        }

        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                @Nullable Bundle savedInstanceState) {
            setStatusBarCoverEnabled(true);

            SchedjoulesFragmentEventDetailsContentLoadingActionsBinding views = DataBindingUtil.inflate(inflater,
                    R.layout.schedjoules_fragment_event_details_content_loading_actions, container, false);

            new EventHeaderView(getActivity(), views.schedjoulesDetailsHeader).update(mEvent);

            mProgressBar = views.schedjoulesEventDetailsHorizontalActionsProgressbar;
            AlphaAnimation anim = new AlphaAnimation(0, 1);
            anim.setDuration(400);
            anim.setStartOffset(200);
            mProgressBar.startAnimation(anim);

            return views.getRoot();
        }

        @Override
        public void onResume() {
            super.onResume();

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                    } finally {
                        mSleepIsOver.set(true);
                        loaderReady();
                    }
                }
            }).start();

            mEventServiceJobQueue.post(new ServiceJob<EventService>() {
                @Override
                public void execute(EventService service) {
                    try {
                        mEventWithDetails.set(service.event(mEvent.uid()));
                        loaderReady();
                    } catch (TimeoutException | InterruptedException | URISyntaxException | ProtocolError
                            | ProtocolException | IOException | RuntimeException e) {
                        Log.e("EventLoaderMF", "Failed to load event: " + mEvent.uid(), e);
                        startTransition(new Revealed(new ForwardTransition(new ErrorMicroFragment(), mTimestamp)));
                    }
                }

                @Override
                public void onTimeOut() {
                    startTransition(new Revealed(new ForwardTransition(new ErrorMicroFragment(), mTimestamp)));
                }
            }, 5000);

            mActionServiceJobQueue.post(new ServiceJob<ActionService>() {
                @Override
                public void execute(ActionService service) {
                    try {
                        mActions.set(service.actions(mEvent.uid()));
                    } catch (TimeoutException | InterruptedException | ProtocolError | IOException
                            | ProtocolException | URISyntaxException | RuntimeException e) {
                        Log.e("EventLoaderMF", "Failed to load actions for event: " + mEvent.uid(), e);
                        // TODO: remove RuntimeException when https://github.com/dmfs/http-client-essentials-suite/issues/36 is fixed
                        // actions could not be loaded - fall back to an empty list
                        mActions.set(Collections.<Link>emptyList());
                    }
                    loaderReady();
                }

                @Override
                public void onTimeOut() {
                    startTransition(new Revealed(new ForwardTransition(new ErrorMicroFragment(), mTimestamp)));
                }
            }, 5000);
        }

        @Override
        public void onDestroy() {
            mEventServiceJobQueue.disconnect();
            mActionServiceJobQueue.disconnect();
            super.onDestroy();
        }

        private void loaderReady() {
            if (mEventWithDetails.get() != null && mActions.get() != null && mSleepIsOver.get()) {
                startTransition(new Revealed(new ForwardTransition(
                        new ShowEventMicroFragment(mEventWithDetails.get(), mActions.get()), mTimestamp)));
            }
        }

        private void startTransition(FragmentTransition fragmentTransition) {
            if (isResumed()) {
                mProgressBar.post(new Runnable() {
                    @Override
                    public void run() {
                        mProgressBar.setVisibility(View.GONE);
                    }
                });
                new FragmentEnvironment<>(this).host().execute(getActivity(), fragmentTransition);
            }
        }

    }
}