Download File
Download Project
Settings
Line Wrap
Themes
default
ambiance
bespin
dracula
eclipse
material
mbo
mdn-like
neat
solarized dark
ttcn
zenburn
LiveDataFragment.java
/* * Copyright (C) 2017 The Android Open Source Project * * 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 android.support.v17.leanback.supportleanbackshowcase.app.room.controller.overview; import android.arch.lifecycle.LifecycleOwner; import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProvider; import android.arch.lifecycle.ViewModelProviders; import android.os.AsyncTask; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v17.leanback.app.BrowseSupportFragment; import android.support.v17.leanback.supportleanbackshowcase.R; import android.support.v17.leanback.supportleanbackshowcase.app.room.adapter.ListAdapter; import android.support.v17.leanback.supportleanbackshowcase.app.room.config.AppConfiguration; import android.support.v17.leanback.supportleanbackshowcase.app.room.controller.app.SampleApplication; import android.support.v17.leanback.supportleanbackshowcase.app.room.db.entity.CategoryEntity; import android.support.v17.leanback.supportleanbackshowcase.app.room.db.entity.VideoEntity; import android.support.v17.leanback.supportleanbackshowcase.app.room.di.adapter.qualifier.ListAdapteWithLiveDataRowPresenterQualifier; import android.support.v17.leanback.supportleanbackshowcase.app.room.network.DownloadCompleteBroadcastReceiver; import android.support.v17.leanback.supportleanbackshowcase.app.room.network.DownloadingTaskDescription; import android.support.v17.leanback.supportleanbackshowcase.app.room.network.NetworkLiveData; import android.support.v17.leanback.supportleanbackshowcase.app.room.ui.LiveDataRowPresenter; import android.support.v17.leanback.supportleanbackshowcase.app.room.ui.LiveDataRowPresenter.DataLoadedListener; import android.support.v17.leanback.supportleanbackshowcase.app.room.ui.VideoCardPresenter; import android.support.v17.leanback.supportleanbackshowcase.app.room.viewmodel.VideosViewModel; import android.support.v17.leanback.widget.HeaderItem; import android.support.v17.leanback.widget.ListRow; import android.support.v17.leanback.widget.OnItemViewClickedListener; import android.support.v17.leanback.widget.OnItemViewSelectedListener; import android.support.v17.leanback.widget.PresenterSelector; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Toast; import dagger.android.AndroidInjector; import dagger.android.support.AndroidSupportInjection; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Map; import javax.inject.Inject; // TOOD: why we need injectable interface here // just like regular class it can specify some component to provide // but if you don't use the dagger component in the code and call the inject(this) method, // it is still basically nothing // so if you don't have injectable interface in the class, no code androidinjection.inject() will // be instrumented, so still nothing happens // but dagger is sophisicated, it will check anyway public class LiveDataFragment extends BrowseSupportFragment implements DownloadCompleteBroadcastReceiver.DownloadCompleteListener, LiveDataRowPresenter.DataLoadedListener { // For debugging purpose private static final Boolean DEBUG = false; private static final String TAG = "LiveDataFragment"; // Resource category private static final String BACKGROUND = "background"; private static final String CARD = "card"; private static final String VIDEO = "video"; @Inject @ListAdapteWithLiveDataRowPresenterQualifier ListAdapter
mRowsAdapter; @Inject Map
viewOnClickListenerMap; @Inject Map
viewOnSelectListenerMap; @Inject Map
onClickListener; @Inject ViewModelProvider.Factory viewModelFactory; @Inject VideoCardPresenter videoCardPresenter; public DataLoadedListener getDataLoadedListener(){ return this; } private VideosViewModel mViewModel; @Override public void onCreate(Bundle savedInstanceState) { AndroidSupportInjection.inject(this); super.onCreate(savedInstanceState); Log.e(TAG, "onCreate: " + " the map is: " + viewOnSelectListenerMap.get(this.getClass())); // set top level adapter setAdapter(mRowsAdapter); // retrive appropriate listener from listener map and set on it setOnItemViewClickedListener(viewOnClickListenerMap.get(this.getClass())); setOnItemViewSelectedListener(viewOnSelectListenerMap.get(this.getClass())); setOnSearchClickedListener(onClickListener.get(this.getClass())); // register broadcast receiver DownloadCompleteBroadcastReceiver.getInstance().registerListener(this); // tweak the ui setHeadersState(HEADERS_ENABLED); setHeadersTransitionOnBackEnabled(true); setTitle(getString(R.string.livedata)); // enable transition prepareEntranceTransition(); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); subscribeNetworkInfo(); mViewModel = ViewModelProviders.of(getActivity(), viewModelFactory) .get(VideosViewModel.class); subscribeUi(mViewModel); } @Override public void onDataLoaded() { startEntranceTransition(); } @Override public void onDownloadingCompleted(final DownloadingTaskDescription desc) { final VideoEntity videoEntity = desc.getVideo(); switch (desc.getCategory()) { case VIDEO: new AsyncTask
() { @Override protected Void doInBackground(Void... voids) { if (AppConfiguration.IS_NETWORK_LATENCY_ENABLED) { addLatency(3000L); } mViewModel.updateDatabase(videoEntity, VIDEO, desc.getStoragePath()); return null; } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); Toast.makeText( getActivity().getApplicationContext(), "video " + videoEntity.getId() + " " + "downloaded", Toast.LENGTH_SHORT).show(); } }.execute(); break; case BACKGROUND: new AsyncTask
() { @Override protected Void doInBackground(Void... voids) { if (AppConfiguration.IS_NETWORK_LATENCY_ENABLED) { addLatency(2000L); } mViewModel.updateDatabase(videoEntity, BACKGROUND, desc.getStoragePath()); return null; } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); Toast.makeText( getActivity().getApplicationContext(), "background" + videoEntity.getId() + " " + "downloaded", Toast.LENGTH_SHORT).show(); } }.execute(); break; case CARD: new AsyncTask
() { @Override protected Void doInBackground(Void... voids) { if (AppConfiguration.IS_NETWORK_LATENCY_ENABLED) { addLatency(1000L); } mViewModel.updateDatabase(videoEntity, CARD, desc.getStoragePath()); return null; } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); Toast.makeText( getActivity().getApplicationContext(), "card " + videoEntity.getId() + " downloaded", Toast.LENGTH_SHORT).show(); } }.execute(); break; } } private void subscribeNetworkInfo() { NetworkLiveData.sync(getActivity()) .observe((LifecycleOwner) getActivity(), new Observer
() { @Override public void onChanged(@Nullable Boolean aBoolean) { if (aBoolean) { getActivity().findViewById(R.id.no_internet).setVisibility(View.GONE); // TODO: an appropriate method to re-create the database } else { getActivity().findViewById(R.id.no_internet) .setVisibility(View.VISIBLE); } } }); } private void subscribeUi(final VideosViewModel viewModel) { viewModel.getAllCategories().observe((LifecycleOwner) getActivity(), new Observer
>() { @Override public void onChanged(@Nullable List
categoryEntities) { if (categoryEntities != null) { List
rows = new ArrayList<>(); // The ListRow here cannot be used with dependency injection, since it // rely on the run time information getCategoryName for (CategoryEntity categoryEntity : categoryEntities) { ListRow row = new ListRow( new HeaderItem(categoryEntity.getCategoryName()), new ListAdapter<>(videoCardPresenter)); rows.add(row); } mRowsAdapter.setItems(rows, new Comparator
() { @Override public int compare(ListRow o1, ListRow o2) { return o1.getId() == o2.getId() ? 0 : -1; } }, new Comparator
() { @Override public int compare(ListRow o1, ListRow o2) { return o1.getHeaderItem().getName() .equals(o2.getHeaderItem().getName()) ? 0 : -1; } }); } } }); } private void addLatency(Long ms) { try { // add 1s latency for video downloading, when network latency option // is enabled. Thread.sleep(ms); } catch (InterruptedException e) { if (DEBUG) { Log.e(TAG, "doInBackground: ", e); } } } }