Commit fbad4c1b authored by Geoffrey Métais's avatar Geoffrey Métais
Browse files

Async browser fragments loading

parent b3099123
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
android:layout_height="fill_parent">
<org.videolan.vlc.widget.HeaderScrollView
android:id="@+id/header"
android:scrollbars="none"
......@@ -77,12 +73,20 @@
android:layout_alignRight="@+id/header"
android:layout_alignTop="@+id/header"
android:background="?attr/header_fadeout_overlay" />
</RelativeLayout>
<ProgressBar
android:id="@+id/loading_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/header"
android:indeterminate="true"
android:layout_centerInParent="true"
android:visibility="gone"/>
<TextView
android:id="@+id/no_media"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/header"
android:gravity="center"
android:text="@string/nomedia"
android:textSize="20sp"
......@@ -91,7 +95,8 @@
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:layout_below="@+id/header">
<org.videolan.vlc.widget.FlingViewGroup
android:id="@+id/content"
android:layout_width="match_parent"
......@@ -155,4 +160,4 @@
android:nextFocusRight="@+id/genres_list" />
</org.videolan.vlc.widget.FlingViewGroup>
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
</RelativeLayout>
......@@ -28,6 +28,7 @@ import org.videolan.libvlc.LibVlcUtil;
import org.videolan.vlc.R;
import org.videolan.vlc.audio.AudioServiceController;
import org.videolan.vlc.gui.video.VideoPlayerActivity;
import org.videolan.vlc.interfaces.IBrowser;
import org.videolan.vlc.interfaces.IRefreshable;
import org.videolan.vlc.interfaces.ISortable;
import org.videolan.vlc.util.Util;
......@@ -59,11 +60,12 @@ import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ListView;
public class DirectoryViewFragment extends ListFragment implements IRefreshable, ISortable, SwipeRefreshLayout.OnRefreshListener {
public class DirectoryViewFragment extends ListFragment implements IBrowser, IRefreshable, ISortable, SwipeRefreshLayout.OnRefreshListener {
public final static String TAG = "VLC/DirectoryViewFragment";
private DirectoryAdapter mDirectoryAdapter;
private SwipeRefreshLayout mSwipeRefreshLayout;
private boolean mReady = true;
/* All subclasses of Fragment must include a public empty constructor. */
public DirectoryViewFragment() { }
......@@ -292,4 +294,15 @@ public class DirectoryViewFragment extends ListFragment implements IRefreshable,
public void onRefresh() {
refresh();
}
@Override
public void setReadyToDisplay(boolean ready) {
mReady = ready;
}
@Override
public void display() {
refresh();
mReady = true;
}
}
......@@ -24,6 +24,7 @@ import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.LibVlcUtil;
import org.videolan.vlc.R;
import org.videolan.vlc.audio.AudioServiceController;
import org.videolan.vlc.interfaces.IBrowser;
import org.videolan.vlc.interfaces.IRefreshable;
import android.os.Bundle;
......@@ -41,11 +42,12 @@ import android.widget.AbsListView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
public class HistoryFragment extends ListFragment implements IRefreshable, SwipeRefreshLayout.OnRefreshListener {
public class HistoryFragment extends ListFragment implements IBrowser, IRefreshable, SwipeRefreshLayout.OnRefreshListener {
public final static String TAG = "VLC/HistoryFragment";
private HistoryAdapter mHistoryAdapter;
private SwipeRefreshLayout mSwipeRefreshLayout;
private boolean mReady = true;
/* All subclasses of Fragment must include a public empty constructor. */
public HistoryFragment() { }
......@@ -151,4 +153,15 @@ public class HistoryFragment extends ListFragment implements IRefreshable, Swipe
public void onRefresh() {
refresh();
}
@Override
public void setReadyToDisplay(boolean ready) {
mReady = ready;
}
@Override
public void display() {
refresh();
mReady = true;
}
}
......@@ -40,6 +40,7 @@ import org.videolan.vlc.gui.audio.EqualizerFragment;
import org.videolan.vlc.gui.video.MediaInfoFragment;
import org.videolan.vlc.gui.video.VideoGridFragment;
import org.videolan.vlc.gui.video.VideoListAdapter;
import org.videolan.vlc.interfaces.IBrowser;
import org.videolan.vlc.interfaces.IRefreshable;
import org.videolan.vlc.interfaces.ISortable;
import org.videolan.vlc.util.AndroidDevices;
......@@ -229,7 +230,13 @@ public class MainActivity extends ActionBarActivity {
/* Set up the sidebar click listener
* no need to invalidate menu for now */
mDrawerToggle = new ActionBarDrawerToggle(this, mRootContainer, R.string.drawer_open, R.string.drawer_close);
mDrawerToggle = new ActionBarDrawerToggle(this, mRootContainer, R.string.drawer_open, R.string.drawer_close){
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
((IBrowser) getSupportFragmentManager().findFragmentById(R.id.fragment_placeholder)).setReadyToDisplay(true);
}
};
// Set the drawer toggle as the DrawerListener
mRootContainer.setDrawerListener(mDrawerToggle);
......@@ -267,8 +274,10 @@ public class MainActivity extends ActionBarActivity {
slideDownAudioPlayer();
/* Switch the fragment */
Fragment fragment = getFragment(entry.id);
((IBrowser)fragment).setReadyToDisplay(false);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_placeholder, getFragment(entry.id), entry.id);
ft.replace(R.id.fragment_placeholder, fragment, entry.id);
ft.commit();
supportInvalidateOptionsMenu();
mCurrentFragment = entry.id;
......@@ -291,7 +300,6 @@ public class MainActivity extends ActionBarActivity {
}else if (entry.attributeID == R.attr.ic_menu_preferences){
startActivityForResult(new Intent(mContext, PreferencesActivity.class), ACTIVITY_RESULT_PREFERENCES);
}
mRootContainer.closeDrawer(mListView);
}
});
......
......@@ -21,7 +21,6 @@
package org.videolan.vlc.gui.audio;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Build;
import android.os.Bundle;
......@@ -50,12 +49,14 @@ import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.PopupMenu.OnMenuItemClickListener;
import android.widget.ProgressBar;
import org.videolan.libvlc.LibVlcUtil;
import org.videolan.libvlc.Media;
import org.videolan.vlc.MediaLibrary;
import org.videolan.vlc.R;
import org.videolan.vlc.audio.AudioServiceController;
import org.videolan.vlc.interfaces.IBrowser;
import org.videolan.vlc.gui.CommonDialogs;
import org.videolan.vlc.gui.MainActivity;
import org.videolan.vlc.util.AndroidDevices;
......@@ -69,7 +70,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class AudioBrowserFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener{
public class AudioBrowserFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener, IBrowser {
public final static String TAG = "VLC/AudioBrowserFragment";
private FlingViewGroup mFlingViewGroup;
......@@ -84,6 +85,7 @@ public class AudioBrowserFragment extends Fragment implements SwipeRefreshLayout
private AudioBrowserListAdapter mArtistsAdapter;
private AudioBrowserListAdapter mAlbumsAdapter;
private AudioBrowserListAdapter mGenresAdapter;
private View mLoading;
private View mEmptyView;
......@@ -93,6 +95,9 @@ public class AudioBrowserFragment extends Fragment implements SwipeRefreshLayout
public final static int MODE_SONG = 2;
public final static int MODE_GENRE = 3;
public final static int MSG_LOADING = 0;
private volatile boolean mReadyToDisplay = true;
/* All subclasses of Fragment must include a public empty constructor. */
public AudioBrowserFragment() { }
......@@ -136,6 +141,7 @@ public class AudioBrowserFragment extends Fragment implements SwipeRefreshLayout
mHeader.setOnKeyListener(keyListener);
mEmptyView = v.findViewById(R.id.no_media);
mLoading = (ProgressBar) v.findViewById(R.id.loading_view);
ListView songsList = (ListView)v.findViewById(R.id.songs_list);
ListView artistList = (ListView)v.findViewById(R.id.artists_list);
......@@ -470,6 +476,43 @@ public class AudioBrowserFragment extends Fragment implements SwipeRefreshLayout
updateLists();
}
@Override
public void setReadyToDisplay(boolean ready) {
if (mLoading != null && mLoading.getVisibility() == View.VISIBLE)
display();
else
mReadyToDisplay = ready;
}
@Override
public void display() {
mReadyToDisplay = true;
if (getActivity() != null)
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(false);
mHandler.removeMessages(MSG_LOADING);
mLoading.setVisibility(View.GONE);
mArtistsAdapter.notifyDataSetChanged();
mSongsAdapter.notifyDataSetChanged();
mAlbumsAdapter.notifyDataSetChanged();
mGenresAdapter.notifyDataSetChanged();
// Refresh the fast scroll data, since SectionIndexer doesn't respect notifyDataSetChanged
int[] lists = {R.id.artists_list, R.id.albums_list, R.id.songs_list, R.id.genres_list};
if (getView() != null) {
ListView l;
for (int r : lists) {
l = (ListView) getView().findViewById(r);
l.setFastScrollEnabled(true);
}
}
focusHelper(false, R.id.artists_list);
}
});
}
private static class AudioBrowserHandler extends WeakHandler<AudioBrowserFragment> {
public AudioBrowserHandler(AudioBrowserFragment owner) {
super(owner);
......@@ -484,22 +527,26 @@ public class AudioBrowserFragment extends Fragment implements SwipeRefreshLayout
case MediaLibrary.MEDIA_ITEMS_UPDATED:
fragment.updateLists();
break;
case MSG_LOADING:
if (!fragment.mReadyToDisplay)
fragment.mLoading.setVisibility(View.VISIBLE);
}
}
};
private void updateLists() {
final Activity context = getActivity();
mSongsAdapter.clear();
mArtistsAdapter.clear();
mAlbumsAdapter.clear();
mGenresAdapter.clear();
final List<Media> audioList = MediaLibrary.getInstance().getAudioItems();
if (audioList.isEmpty()){
mSwipeRefreshLayout.setRefreshing(false);
mEmptyView.setVisibility(View.VISIBLE);
focusHelper(true, R.id.artists_list);
} else {
mEmptyView.setVisibility(View.GONE);
mHandler.sendEmptyMessageDelayed(MSG_LOADING, 300);
new Thread(new Runnable() {
@Override
......@@ -517,23 +564,8 @@ public class AudioBrowserFragment extends Fragment implements SwipeRefreshLayout
Collections.sort(audioList, MediaComparators.byGenre);
mGenresAdapter.addAll(audioList, AudioBrowserListAdapter.TYPE_GENRES);
context.runOnUiThread(new Runnable() {
@Override
public void run() {
// Refresh the fast scroll data, since SectionIndexer doesn't respect notifyDataSetChanged
int[] lists = {R.id.artists_list, R.id.albums_list, R.id.songs_list, R.id.genres_list};
if (getView() != null) {
ListView l;
for (int r : lists) {
l = (ListView) getView().findViewById(r);
l.setFastScrollEnabled(false);
l.setFastScrollEnabled(true);
}
}
focusHelper(false, R.id.artists_list);
mSwipeRefreshLayout.setRefreshing(false);
}
});
if (mReadyToDisplay)
display();
}
}).start();
}
......
......@@ -215,7 +215,6 @@ public class AudioBrowserListAdapter extends BaseAdapter implements SectionIndex
firstSeparator = false;
}
}
notifyDataSetChanged();
}
public void addSeparator(String title, Media media) {
......@@ -228,7 +227,6 @@ public class AudioBrowserListAdapter extends BaseAdapter implements SectionIndex
mSeparatorItemMap.put(title, item);
mItems.add(item);
}
notifyDataSetChanged();
}
/**
......
......@@ -34,6 +34,7 @@ import org.videolan.vlc.MediaLibrary;
import org.videolan.vlc.R;
import org.videolan.vlc.Thumbnailer;
import org.videolan.vlc.audio.AudioServiceController;
import org.videolan.vlc.interfaces.IBrowser;
import org.videolan.vlc.gui.CommonDialogs;
import org.videolan.vlc.gui.MainActivity;
import org.videolan.vlc.interfaces.ISortable;
......@@ -74,7 +75,7 @@ import android.widget.PopupMenu;
import android.widget.PopupMenu.OnMenuItemClickListener;
import android.widget.TextView;
public class VideoGridFragment extends SherlockGridFragment implements ISortable, VideoBrowserInterface, SwipeRefreshLayout.OnRefreshListener {
public class VideoGridFragment extends SherlockGridFragment implements IBrowser, ISortable, VideoBrowserInterface, SwipeRefreshLayout.OnRefreshListener {
public final static String TAG = "VLC/VideoListFragment";
......@@ -101,6 +102,7 @@ public class VideoGridFragment extends SherlockGridFragment implements ISortable
private SwipeRefreshLayout mSwipeRefreshLayout;
private AudioServiceController mAudioController;
private boolean mReady = true;
// Gridview position saved in onPause()
private int mGVFirstVisiblePos;
......@@ -397,38 +399,41 @@ public class VideoGridFragment extends SherlockGridFragment implements ISortable
public void updateList() {
if (!mSwipeRefreshLayout.isRefreshing())
mSwipeRefreshLayout.setRefreshing(true);
List<Media> itemList = mMediaLibrary.getVideoItems();
final List<Media> itemList = mMediaLibrary.getVideoItems();
if (mThumbnailer != null)
mThumbnailer.clearJobs();
else
Log.w(TAG, "Can't generate thumbnails, the thumbnailer is missing");
mVideoAdapter.setNotifyOnChange(false);
mVideoAdapter.clear();
if (itemList.size() > 0) {
if (mGroup != null || itemList.size() <= 10) {
for (Media item : itemList) {
if (mGroup == null || item.getTitle().startsWith(mGroup)) {
mVideoAdapter.add(item);
if (mThumbnailer != null)
mThumbnailer.addJob(item);
new Thread(new Runnable() {
@Override
public void run() {
if (mGroup != null || itemList.size() <= 10) {
for (Media item : itemList) {
if (mGroup == null || item.getTitle().startsWith(mGroup)) {
mVideoAdapter.add(item);
if (mThumbnailer != null)
mThumbnailer.addJob(item);
}
}
}
else {
List<MediaGroup> groups = MediaGroup.group(itemList);
for (MediaGroup item : groups) {
mVideoAdapter.add(item.getMedia());
if (mThumbnailer != null)
mThumbnailer.addJob(item);
}
}
if (mReady)
display();
}
}
else {
List<MediaGroup> groups = MediaGroup.group(itemList);
for (MediaGroup item : groups) {
mVideoAdapter.add(item.getMedia());
if (mThumbnailer != null)
mThumbnailer.addJob(item);
}
}
mVideoAdapter.sort();
mGVFirstVisiblePos = mGridView.getFirstVisiblePosition();
mGridView.setSelection(mGVFirstVisiblePos);
mGridView.requestFocus();
focusHelper(false);
}).start();
} else
focusHelper(true);
stopRefresh();
......@@ -477,6 +482,29 @@ public class VideoGridFragment extends SherlockGridFragment implements ISortable
@Override
public void onRefresh() {
updateList();
if (getActivity()!=null)
MediaLibrary.getInstance().loadMediaItems(getActivity(), true);
}
@Override
public void setReadyToDisplay(boolean ready) {
mReady = ready;
}
@Override
public void display() {
if (getActivity() != null)
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mVideoAdapter.sort();
mVideoAdapter.notifyDataSetChanged();
mGVFirstVisiblePos = mGridView.getFirstVisiblePosition();
mGridView.setSelection(mGVFirstVisiblePos);
mGridView.requestFocus();
focusHelper(false);
mReady = true;
}
});
}
}
/*****************************************************************************
* AudioBrowserListAdapter.java
*****************************************************************************
* Copyright © 2011-2014 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
package org.videolan.vlc.interfaces;
public interface IBrowser {
void setReadyToDisplay(boolean ready);
void display();
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment