OSDN Git Service

Eleven: Make Images load a bit faster
[android-x86/packages-apps-Eleven.git] / src / com / cyngn / eleven / ui / fragments / AlbumFragment.java
1 /*
2  * Copyright (C) 2012 Andrew Neal Licensed under the Apache License, Version 2.0
3  * (the "License"); you may not use this file except in compliance with the
4  * License. You may obtain a copy of the License at
5  * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
6  * or agreed to in writing, software distributed under the License is
7  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8  * KIND, either express or implied. See the License for the specific language
9  * governing permissions and limitations under the License.
10  */
11
12 package com.cyngn.eleven.ui.fragments;
13
14 import android.os.Bundle;
15 import android.os.SystemClock;
16 import android.support.v4.app.LoaderManager.LoaderCallbacks;
17 import android.support.v4.content.Loader;
18 import android.view.LayoutInflater;
19 import android.view.View;
20 import android.view.ViewGroup;
21 import android.widget.AbsListView;
22 import android.widget.AbsListView.OnScrollListener;
23 import android.widget.AdapterView;
24 import android.widget.AdapterView.OnItemClickListener;
25 import android.widget.GridView;
26
27 import com.cyngn.eleven.MusicStateListener;
28 import com.cyngn.eleven.R;
29 import com.cyngn.eleven.adapters.AlbumAdapter;
30 import com.cyngn.eleven.adapters.PagerAdapter;
31 import com.cyngn.eleven.loaders.AlbumLoader;
32 import com.cyngn.eleven.model.Album;
33 import com.cyngn.eleven.recycler.RecycleHolder;
34 import com.cyngn.eleven.sectionadapter.SectionCreator;
35 import com.cyngn.eleven.sectionadapter.SectionListContainer;
36 import com.cyngn.eleven.ui.activities.BaseActivity;
37 import com.cyngn.eleven.ui.fragments.phone.MusicBrowserFragment;
38 import com.cyngn.eleven.utils.AlbumPopupMenuHelper;
39 import com.cyngn.eleven.utils.ApolloUtils;
40 import com.cyngn.eleven.utils.MusicUtils;
41 import com.cyngn.eleven.utils.NavUtils;
42 import com.cyngn.eleven.utils.PopupMenuHelper;
43 import com.cyngn.eleven.widgets.IPopupMenuCallback;
44 import com.cyngn.eleven.widgets.LoadingEmptyContainer;
45 import com.viewpagerindicator.TitlePageIndicator;
46
47 /**
48  * This class is used to display all of the albums on a user's device.
49  * 
50  * @author Andrew Neal (andrewdneal@gmail.com)
51  */
52 public class AlbumFragment extends MusicBrowserFragment implements
53         LoaderCallbacks<SectionListContainer<Album>>, OnScrollListener,
54         OnItemClickListener, MusicStateListener {
55
56     /**
57      * Grid view column count. ONE - list, TWO - normal grid, FOUR - landscape
58      */
59     private static final int TWO = 2, FOUR = 4;
60
61     /**
62      * Fragment UI
63      */
64     private ViewGroup mRootView;
65
66     /**
67      * The adapter for the grid
68      */
69     private AlbumAdapter mAdapter;
70
71     /**
72      * The grid view
73      */
74     private GridView mGridView;
75
76     /**
77      * Pop up menu helper
78      */
79     private PopupMenuHelper mPopupMenuHelper;
80
81     /**
82      * This holds the loading progress bar as well as the no results message
83      */
84     private LoadingEmptyContainer mLoadingEmptyContainer;
85
86     @Override
87     public int getLoaderId() {
88         return PagerAdapter.MusicFragments.ALBUM.ordinal();
89     }
90
91     /**
92      * {@inheritDoc}
93      */
94     @Override
95     public void onCreate(final Bundle savedInstanceState) {
96         super.onCreate(savedInstanceState);
97
98         mPopupMenuHelper = new AlbumPopupMenuHelper(getActivity(), getFragmentManager()) {
99             public Album getAlbum(int position) {
100                 return mAdapter.getItem(position);
101             }
102         };
103
104         int layout = R.layout.grid_items_normal;
105
106         mAdapter = new AlbumAdapter(getActivity(), layout);
107         mAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() {
108             @Override
109             public void onPopupMenuClicked(View v, int position) {
110                 mPopupMenuHelper.showPopupMenu(v, position);
111             }
112         });
113     }
114
115     /**
116      * {@inheritDoc}
117      */
118     @Override
119     public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
120             final Bundle savedInstanceState) {
121         mRootView = (ViewGroup)inflater.inflate(R.layout.grid_base, null);
122         initGridView();
123
124         // Register the music status listener
125         ((BaseActivity)getActivity()).setMusicStateListenerListener(this);
126
127         return mRootView;
128     }
129
130     /**
131      * {@inheritDoc}
132      */
133     @Override
134     public void onActivityCreated(final Bundle savedInstanceState) {
135         super.onActivityCreated(savedInstanceState);
136         // Enable the options menu
137         setHasOptionsMenu(true);
138         // Start the loader
139         initLoader(null, this);
140     }
141
142     @Override
143     public void onDestroyView() {
144         super.onDestroyView();
145
146         ((BaseActivity)getActivity()).removeMusicStateListenerListener(this);
147     }
148
149
150     /**
151      * {@inheritDoc}
152      */
153     @Override
154     public void onPause() {
155         super.onPause();
156         mAdapter.flush();
157     }
158
159     /**
160      * {@inheritDoc}
161      */
162     @Override
163     public void onScrollStateChanged(final AbsListView view, final int scrollState) {
164         // Pause disk cache access to ensure smoother scrolling
165         if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
166             mAdapter.setPauseDiskCache(true);
167         } else {
168             mAdapter.setPauseDiskCache(false);
169             mAdapter.notifyDataSetChanged();
170         }
171     }
172
173     /**
174      * {@inheritDoc}
175      */
176     @Override
177     public void onItemClick(final AdapterView<?> parent, final View view, final int position,
178             final long id) {
179         Album album = mAdapter.getItem(position);
180         NavUtils.openAlbumProfile(getActivity(), album.mAlbumName, album.mArtistName, album.mAlbumId);
181     }
182
183     /**
184      * {@inheritDoc}
185      */
186     @Override
187     public Loader<SectionListContainer<Album>> onCreateLoader(final int id, final Bundle args) {
188         mLoadingEmptyContainer.showLoading();
189         // if we ever decide to add section headers for grid items, we can pass a compartor
190         // instead of null
191         return new SectionCreator<Album>(getActivity(), new AlbumLoader(getActivity()), null);
192     }
193
194     /**
195      * {@inheritDoc}
196      */
197     @Override
198     public void onLoadFinished(final Loader<SectionListContainer<Album>> loader,
199                                final SectionListContainer<Album> data) {
200         // Check for any errors
201         if (data.mListResults.isEmpty()) {
202             mLoadingEmptyContainer.showNoResults();
203             return;
204         }
205
206         mAdapter.setData(data.mListResults);
207     }
208
209     /**
210      * {@inheritDoc}
211      */
212     @Override
213     public void onLoaderReset(final Loader<SectionListContainer<Album>> loader) {
214         // Clear the data in the adapter
215         mAdapter.unload();
216     }
217
218     /**
219      * Scrolls the list to the currently playing album when the user touches the
220      * header in the {@link TitlePageIndicator}.
221      */
222     public void scrollToCurrentAlbum() {
223         final int currentAlbumPosition = getItemPositionByAlbum();
224
225         if (currentAlbumPosition != 0) {
226             mGridView.setSelection(currentAlbumPosition);
227         }
228     }
229
230     /**
231      * @return The position of an item in the list or grid based on the id of
232      *         the currently playing album.
233      */
234     private int getItemPositionByAlbum() {
235         final long albumId = MusicUtils.getCurrentAlbumId();
236         if (mAdapter == null) {
237             return 0;
238         }
239
240         int position = mAdapter.getItemPosition(albumId);
241
242         // if for some reason we don't find the item, just jump to the top
243         if (position < 0) {
244             return 0;
245         }
246
247         return position;
248     }
249
250     /**
251      * Restarts the loader.
252      */
253     public void refresh() {
254         // Wait a moment for the preference to change.
255         SystemClock.sleep(10);
256         restartLoader();
257     }
258
259     /**
260      * {@inheritDoc}
261      */
262     @Override
263     public void onScroll(final AbsListView view, final int firstVisibleItem,
264             final int visibleItemCount, final int totalItemCount) {
265         // Nothing to do
266     }
267
268     /**
269      * {@inheritDoc}
270      */
271     @Override
272     public void restartLoader() {
273         // Update the list when the user deletes any items
274         restartLoader(null, this);
275     }
276
277     /**
278      * {@inheritDoc}
279      */
280     @Override
281     public void onMetaChanged() {
282         // Nothing to do
283     }
284
285     @Override
286     public void onPlaylistChanged() {
287         // Nothing to do
288     }
289
290     /**
291      * Sets up various helpers for both the list and grid
292      * 
293      * @param list The list or grid
294      */
295     private void initAbsListView(final AbsListView list) {
296         // Release any references to the recycled Views
297         list.setRecyclerListener(new RecycleHolder());
298         // Show the albums and songs from the selected artist
299         list.setOnItemClickListener(this);
300         // To help make scrolling smooth
301         list.setOnScrollListener(this);
302     }
303
304     /**
305      * Sets up the grid view
306      */
307     private void initGridView() {
308         int columns = ApolloUtils.isLandscape(getActivity()) ? FOUR : TWO;
309         mAdapter.setNumColumns(columns);
310         // Initialize the grid
311         mGridView = (GridView)mRootView.findViewById(R.id.grid_base);
312         // Set the data behind the grid
313         mGridView.setAdapter(mAdapter);
314         // Set up the helpers
315         initAbsListView(mGridView);
316         mGridView.setNumColumns(columns);
317
318         // Show progress bar
319         mLoadingEmptyContainer = (LoadingEmptyContainer)mRootView.findViewById(R.id.loading_empty_container);
320         mGridView.setEmptyView(mLoadingEmptyContainer);
321     }
322 }