diff --git a/app/build.gradle b/app/build.gradle index f7e7d83..33c8545 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -59,6 +59,9 @@ dependencies { //litePal implementation 'org.litepal.android:java:3.0.0' //水波纹按钮 - compile 'com.patrickpissurno:ripple-effect:1.3.1' + implementation 'com.patrickpissurno:ripple-effect:1.3.1' + //加载动画 + implementation 'com.wang.avi:library:2.1.3' + } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 088a622..ad0acec 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,9 +10,9 @@ diff --git a/app/src/main/java/com/example/musicplayer/adapter/AlbumSongAdapter.java b/app/src/main/java/com/example/musicplayer/adapter/AlbumSongAdapter.java index 3067e4d..427a9ca 100644 --- a/app/src/main/java/com/example/musicplayer/adapter/AlbumSongAdapter.java +++ b/app/src/main/java/com/example/musicplayer/adapter/AlbumSongAdapter.java @@ -10,6 +10,7 @@ import android.widget.TextView; import com.andexert.library.RippleView; import com.example.musicplayer.R; +import com.example.musicplayer.constant.MyApplication; import com.example.musicplayer.entiy.AlbumSong; import com.example.musicplayer.util.FileHelper; @@ -58,13 +59,18 @@ public class AlbumSongAdapter extends RecyclerView.Adapter> mAlbumCollectionList; + private String[] mGroupStrings; //一级标题 + private List> mAlbumCollectionList; //二级收藏歌单列表 private Context mContext; - private OnChildItemClickListener mChildClickListener; + private OnChildItemClickListener mChildClickListener; //二级item的点击监听 public ExpandableListViewAdapter(Context context, String[] groupStrings, List> albumCollectionList) { @@ -33,6 +33,7 @@ public class ExpandableListViewAdapter extends BaseExpandableListAdapter { mGroupStrings = groupStrings; mContext = context; } + //提供给外部使用 public void setOnChildItemClickListener(OnChildItemClickListener onChildItemClickListener){ mChildClickListener=onChildItemClickListener; } @@ -72,6 +73,7 @@ public class ExpandableListViewAdapter extends BaseExpandableListAdapter { return true; } + //绘制一级列表 @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { View view; @@ -81,13 +83,13 @@ public class ExpandableListViewAdapter extends BaseExpandableListAdapter { groupViewHolder = new GroupViewHolder(); groupViewHolder.groupTextView = view.findViewById(R.id.tv_new_song); groupViewHolder.pointIv = view.findViewById(R.id.iv_point); - groupViewHolder.addIv = view.findViewById(R.id.iv_add); view.setTag(groupViewHolder); } else { view = convertView; groupViewHolder = (GroupViewHolder) view.getTag(); } groupViewHolder.groupTextView.setText(mGroupStrings[groupPosition]); + //根据展开的状态来改变箭头方向 if (isExpanded) { groupViewHolder.pointIv.setImageResource(R.drawable.up); } else { @@ -97,6 +99,7 @@ public class ExpandableListViewAdapter extends BaseExpandableListAdapter { } + //绘制二级列表 @Override public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { View view; @@ -118,6 +121,7 @@ public class ExpandableListViewAdapter extends BaseExpandableListAdapter { childViewHolder.authorTv.setText(mAlbumCollectionList.get(groupPosition).get(childPosition).getSingerName()); CommonUtil.setImgWithGlide(mContext, mAlbumCollectionList.get(groupPosition).get(childPosition).getAlbumPic(), childViewHolder.faceIv); + //点击水波纹效果,结束后开始点击效果 childViewHolder.childView.setOnRippleCompleteListener(new RippleView.OnRippleCompleteListener() { @Override public void onComplete(RippleView rippleView) { @@ -136,7 +140,6 @@ public class ExpandableListViewAdapter extends BaseExpandableListAdapter { class GroupViewHolder { private TextView groupTextView; private ImageView pointIv; - private ImageView addIv; } class ChildViewHolder { diff --git a/app/src/main/java/com/example/musicplayer/base/BaseObserver.java b/app/src/main/java/com/example/musicplayer/base/BaseObserver.java new file mode 100644 index 0000000..36e5874 --- /dev/null +++ b/app/src/main/java/com/example/musicplayer/base/BaseObserver.java @@ -0,0 +1,44 @@ +package com.example.musicplayer.base; + +import android.widget.Toast; + +import com.example.musicplayer.constant.Constant; +import com.example.musicplayer.entiy.AlbumSong; +import com.example.musicplayer.util.CommonUtil; +import com.example.musicplayer.util.RxApiManager; + +import java.net.UnknownHostException; + +import io.reactivex.Observable; +import io.reactivex.Observer; +import io.reactivex.disposables.Disposable; + +/** + * Created by 残渊 on 2018/12/5. + */ + +public abstract class BaseObserver implements Observer { + private BaseActivity context; + + public BaseObserver(BaseActivity context) { + this.context = context; + } + + @Override + public void onSubscribe(Disposable d) { + RxApiManager.get().add(Constant.ALBUM,d); + } + + @Override + public void onError(Throwable e) { + if(e instanceof UnknownHostException){ + onComplete(); + CommonUtil.showToast(context,"当前网络不可用,请检查当前网络"); + } + } + + @Override + public void onComplete() { + } +} + diff --git a/app/src/main/java/com/example/musicplayer/callback/RxActionManager.java b/app/src/main/java/com/example/musicplayer/callback/RxActionManager.java new file mode 100644 index 0000000..1aee512 --- /dev/null +++ b/app/src/main/java/com/example/musicplayer/callback/RxActionManager.java @@ -0,0 +1,17 @@ +package com.example.musicplayer.callback; + + +import io.reactivex.disposables.Disposable; + +/** + * 主要管理rxJava的Subscription描述 + * Created by 残渊 on 2018/12/5. + */ + +public interface RxActionManager { + void add(T tag, Disposable d); + void remove(T tag); + void cancel(T tag); + void cancelAll(); +} + diff --git a/app/src/main/java/com/example/musicplayer/constant/Constant.java b/app/src/main/java/com/example/musicplayer/constant/Constant.java index 2892448..be2b00c 100644 --- a/app/src/main/java/com/example/musicplayer/constant/Constant.java +++ b/app/src/main/java/com/example/musicplayer/constant/Constant.java @@ -14,4 +14,10 @@ public class Constant { public static final int LIST_TYPE_LOVE=6; public static final int LIST_TYPE_HISTORY=7; public static final int HISTORY_MAX_SIZE=100; + public static final String LOCAL_IMG="local_img"; + public static final String SEARCH_SONG= "search_song"; + public static final String SEARCH_SONG_MORE= "search_song_more"; + public static final String SEARCH_ALBUM="search_album"; + public static final String SEARCH_ALBUM_MORE="search_album_more"; + public static final String ALBUM="album"; } diff --git a/app/src/main/java/com/example/musicplayer/contract/IAlbumSongContract.java b/app/src/main/java/com/example/musicplayer/contract/IAlbumSongContract.java index 8c1b90d..94cf6d4 100644 --- a/app/src/main/java/com/example/musicplayer/contract/IAlbumSongContract.java +++ b/app/src/main/java/com/example/musicplayer/contract/IAlbumSongContract.java @@ -19,7 +19,9 @@ public interface IAlbumSongContract { void setAlbumSongList(List songList); //成功获取专辑歌曲后填充列表 void showAlbumSongError();//获取专辑失败 void showAlbumMessage(String name,String singer,String company,String desc); //展示专辑详细 - void showNetError(); //网络错误 + void showLoading(); //显示进度 + void hideLoading(); //隐藏进度 + void showNetError(); //显示网络错误 } interface Presenter{ void getAlbumDetail(String id,int type); //获取专辑的更多信息 @@ -29,5 +31,7 @@ public interface IAlbumSongContract { void getAlbumError(); //接口出现问题 void insertAllAlbumSong(ArrayList songList); //将专辑歌曲添加到数据库 + + void showNetError(); //显示网络错误 } } diff --git a/app/src/main/java/com/example/musicplayer/contract/ISearchContentContract.java b/app/src/main/java/com/example/musicplayer/contract/ISearchContentContract.java index 910a920..0c9ae48 100644 --- a/app/src/main/java/com/example/musicplayer/contract/ISearchContentContract.java +++ b/app/src/main/java/com/example/musicplayer/contract/ISearchContentContract.java @@ -31,6 +31,9 @@ public interface ISearchContentContract { void searchAlbumSuccess(List albumList); //获取专辑成功 void searchAlbumMoreSuccess(List songListBeans); //搜索更多内容成功 void searchAlbumError(); //获取专辑失败 + void showLoading(); //显示进度 + void hideLoading(); //隐藏进度 + void showNetError(); //显示网络错误 } interface Presenter{ void search(String seek,int offset); //搜索 @@ -47,5 +50,9 @@ public interface ISearchContentContract { void searchAlbumMore(String seek,int offset);//搜索更多专辑 void searchAlbumMoreSuccess(List songListBeans); //搜索更多内容成功 + + void networkError();//网络错误 + + } } diff --git a/app/src/main/java/com/example/musicplayer/https/NetWork.java b/app/src/main/java/com/example/musicplayer/https/NetWork.java index 01dbaaa..7633297 100644 --- a/app/src/main/java/com/example/musicplayer/https/NetWork.java +++ b/app/src/main/java/com/example/musicplayer/https/NetWork.java @@ -6,6 +6,8 @@ import com.example.musicplayer.https.api.AlbumApi; import com.example.musicplayer.https.api.SearchApi; import com.example.musicplayer.https.api.SingerImgApi; +import org.reactivestreams.Subscription; + import java.util.concurrent.TimeUnit; import okhttp3.OkHttpClient; @@ -24,7 +26,7 @@ import static com.example.musicplayer.constant.BaseUri.SINGER_URL; */ public class NetWork { - private static okhttp3.OkHttpClient.Builder builder = new OkHttpClient.Builder().connectTimeout(20, TimeUnit.SECONDS); + private static okhttp3.OkHttpClient.Builder builder = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS); private static Converter.Factory gsonConverterFactory = GsonConverterFactory.create(); private static CallAdapter.Factory rxJavaCallAdapterFactory = RxJava2CallAdapterFactory.create(); private static SingerImgApi singerImgApi; diff --git a/app/src/main/java/com/example/musicplayer/model/AlbumSongModel.java b/app/src/main/java/com/example/musicplayer/model/AlbumSongModel.java index 6ae8176..f5b116d 100644 --- a/app/src/main/java/com/example/musicplayer/model/AlbumSongModel.java +++ b/app/src/main/java/com/example/musicplayer/model/AlbumSongModel.java @@ -2,14 +2,17 @@ package com.example.musicplayer.model; import android.util.Log; +import com.example.musicplayer.constant.Constant; import com.example.musicplayer.contract.IAlbumSongContract; import com.example.musicplayer.entiy.AlbumSong; import com.example.musicplayer.entiy.OnlineSong; import com.example.musicplayer.https.NetWork; +import com.example.musicplayer.util.RxApiManager; import org.litepal.LitePal; import org.litepal.crud.LitePalSupport; +import java.net.UnknownHostException; import java.util.ArrayList; import io.reactivex.Observer; @@ -17,43 +20,49 @@ import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; +import static com.example.musicplayer.view.AlbumSongFragment.ALBUM_SONG; + /** * Created by 残渊 on 2018/11/27. */ public class AlbumSongModel implements IAlbumSongContract.Model { - private static final String TAG="AlbumSongModel"; + private static final String TAG = "AlbumSongModel"; private IAlbumSongContract.Presenter mPresenter; - public AlbumSongModel(IAlbumSongContract.Presenter presenter){ + public AlbumSongModel(IAlbumSongContract.Presenter presenter) { mPresenter = presenter; } @Override - public void getAlbumDetail(String id,final int type) { + public void getAlbumDetail(String id, final int type) { NetWork.getAlbumApi().getAlbumSong(id) .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { - + RxApiManager.get().add(Constant.ALBUM, d); } @Override public void onNext(AlbumSong value) { - if(value.getResult().equals("SUCCESS")){ - mPresenter.getAlbumDetailSuccess(type,value.getData().getSongs(), - value.getData().getName(),value.getData().getSinger(), - value.getData().getCompany(),value.getData().getDesc()); - }else{ + if (value.getResult().equals("SUCCESS")) { + mPresenter.getAlbumDetailSuccess(type, value.getData().getSongs(), + value.getData().getName(), value.getData().getSinger(), + value.getData().getCompany(), value.getData().getDesc()); + } else { mPresenter.getAlbumDetailError(); } } @Override public void onError(Throwable e) { - Log.d(TAG, "onError: "+e.toString()); - mPresenter.getAlbumError(); + Log.d(TAG, "onError: " + e.toString()); + if (e instanceof UnknownHostException && type == ALBUM_SONG) { + mPresenter.showNetError(); + } else { + mPresenter.getAlbumError(); + } } @Override @@ -70,10 +79,10 @@ public class AlbumSongModel implements IAlbumSongContract.Model { @Override public void run() { LitePal.deleteAll(OnlineSong.class); - for(int i=0;i() { @Override public void onSubscribe(Disposable d) { - + RxApiManager.get().add(Constant.LOCAL_IMG,d); } @Override diff --git a/app/src/main/java/com/example/musicplayer/model/SearchContentModel.java b/app/src/main/java/com/example/musicplayer/model/SearchContentModel.java index 8023b2c..02bb323 100644 --- a/app/src/main/java/com/example/musicplayer/model/SearchContentModel.java +++ b/app/src/main/java/com/example/musicplayer/model/SearchContentModel.java @@ -2,11 +2,14 @@ package com.example.musicplayer.model; import android.util.Log; +import com.example.musicplayer.constant.Constant; import com.example.musicplayer.contract.ISearchContentContract; import com.example.musicplayer.entiy.Album; import com.example.musicplayer.entiy.SeachSong; import com.example.musicplayer.https.NetWork; +import com.example.musicplayer.util.RxApiManager; +import java.net.UnknownHostException; import java.util.ArrayList; import io.reactivex.Observer; @@ -28,12 +31,12 @@ public class SearchContentModel implements ISearchContentContract.Model { @Override public void search(String seek, int offset) { - NetWork.getSearchApi().search(seek,offset) + NetWork.getSearchApi().search(seek, offset) .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { - + RxApiManager.get().add(Constant.SEARCH_SONG, d); } @Override @@ -43,7 +46,9 @@ public class SearchContentModel implements ISearchContentContract.Model { @Override public void onError(Throwable e) { - mPresenter.searchError(); + if (e instanceof UnknownHostException) { + mPresenter.networkError(); + } Log.d(TAG, "onError: " + e.toString()); } @@ -56,13 +61,13 @@ public class SearchContentModel implements ISearchContentContract.Model { } @Override - public void searchMore(String seek,int offset) { + public void searchMore(String seek, int offset) { NetWork.getSearchApi().search(seek, offset) .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { - + RxApiManager.get().add(Constant.SEARCH_SONG_MORE, d); } @Override @@ -94,26 +99,30 @@ public class SearchContentModel implements ISearchContentContract.Model { @Override public void searchAlbum(String seek, int offset) { - NetWork.getSearchApi().searchAlbum(seek,offset) + NetWork.getSearchApi().searchAlbum(seek, offset) .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { - + RxApiManager.get().add(Constant.SEARCH_ALBUM, d); } @Override public void onNext(Album value) { - if(value.getResult().equals("SUCCESS")){ + if (value.getResult().equals("SUCCESS")) { mPresenter.searchAlbumSuccess(value.getData()); - }else{ + } else { mPresenter.searchAlbumError(); } } @Override public void onError(Throwable e) { - mPresenter.searchAlbumError(); + if (e instanceof UnknownHostException) { + mPresenter.networkError(); + } else { + mPresenter.searchAlbumError(); + } Log.d(TAG, "onError: searchAlbumError" + e.toString()); } @@ -132,7 +141,7 @@ public class SearchContentModel implements ISearchContentContract.Model { .subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { - + RxApiManager.get().add(Constant.SEARCH_ALBUM_MORE, d); } @Override diff --git a/app/src/main/java/com/example/musicplayer/presenter/AlbumSongPresenter.java b/app/src/main/java/com/example/musicplayer/presenter/AlbumSongPresenter.java index 50a0210..4b763d1 100644 --- a/app/src/main/java/com/example/musicplayer/presenter/AlbumSongPresenter.java +++ b/app/src/main/java/com/example/musicplayer/presenter/AlbumSongPresenter.java @@ -1,8 +1,10 @@ package com.example.musicplayer.presenter; +import android.os.Handler; import android.util.Log; import com.example.musicplayer.base.BasePresenter; +import com.example.musicplayer.constant.Constant; import com.example.musicplayer.contract.IAlbumSongContract; import com.example.musicplayer.entiy.AlbumSong; import com.example.musicplayer.model.AlbumSongModel; @@ -11,36 +13,52 @@ import com.example.musicplayer.view.AlbumSongFragment; import java.util.ArrayList; import java.util.List; +import static com.example.musicplayer.view.AlbumSongFragment.ALBUM_SONG; + + /** * Created by 残渊 on 2018/11/27. */ public class AlbumSongPresenter extends BasePresenter implements IAlbumSongContract.Presenter { - private final static String TAG="AlbumSongPresenter"; + private final static String TAG = "AlbumSongPresenter"; private AlbumSongModel mModel; + private Handler mHandler = new Handler(); public AlbumSongPresenter() { mModel = new AlbumSongModel(this); } @Override - public void getAlbumDetail(String id,int type) { - mModel.getAlbumDetail(id,type); + public void getAlbumDetail(String id, int type) { + mModel.getAlbumDetail(id, type); + if (type == ALBUM_SONG) { + if (isAttachView()) { + getMvpView().showLoading(); + } + } } @Override - public void getAlbumDetailSuccess(int type, List songList, - String name, String singer, String company, String desc) { - if (isAttachView()) { - if (type == AlbumSongFragment.ALBUM_SONG) { - getMvpView().setAlbumSongList(songList); - Log.d(TAG, "getAlbumDetailSuccess: "+songList.size()); - } else { - getMvpView().showAlbumMessage(name, singer, company, desc); + public void getAlbumDetailSuccess(final int type, final List songList, + final String name, final String singer, final String company, final String desc) { + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + if (isAttachView()) { + if (type == ALBUM_SONG) { + getMvpView().setAlbumSongList(songList); + getMvpView().hideLoading(); + } else { + getMvpView().showAlbumMessage(name, singer, company, desc); + } + + } } - } + }, 1000); + } @Override @@ -53,7 +71,7 @@ public class AlbumSongPresenter extends BasePresenter i @Override public void getAlbumError() { if (isAttachView()) { - getMvpView().showNetError(); + getMvpView().showAlbumSongError(); } } @@ -61,4 +79,17 @@ public class AlbumSongPresenter extends BasePresenter i public void insertAllAlbumSong(ArrayList songList) { mModel.insertAllAlbumSong(songList); } + + @Override + public void showNetError() { + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + if (isAttachView()) { + getMvpView().showNetError(); + } + } + }, 1000); + + } } diff --git a/app/src/main/java/com/example/musicplayer/presenter/SearchContentPresenter.java b/app/src/main/java/com/example/musicplayer/presenter/SearchContentPresenter.java index 96a2e88..b3f9b65 100644 --- a/app/src/main/java/com/example/musicplayer/presenter/SearchContentPresenter.java +++ b/app/src/main/java/com/example/musicplayer/presenter/SearchContentPresenter.java @@ -26,6 +26,9 @@ public class SearchContentPresenter extends BasePresenter songListBeans) { + public void searchSuccess(final ArrayList songListBeans) { + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + if(isAttachView()){ + getMvpView().hideLoading(); + getMvpView().setSongsList(songListBeans); + } + } + },500); - if(isAttachView()){ - getMvpView().setSongsList(songListBeans); - } } @Override @@ -82,12 +91,16 @@ public class SearchContentPresenter extends BasePresenter albumList) { if(isAttachView()){ getMvpView().searchAlbumSuccess(albumList); + getMvpView().hideLoading(); } } @@ -95,6 +108,7 @@ public class SearchContentPresenter extends BasePresenter= mLocalSongList.size()) { mCurrent = 0; @@ -242,15 +242,14 @@ public class PlayerService extends Service { saveOnlineSongInfo(mCurrent); mPlayStatusBinder.play(Constant.LIST_TYPE_ONLINE); sendBroadcast(new Intent(BroadcastName.ONLINE_ALBUM_SONG_Change));//专辑列表的改变 - } else if(mListType == Constant.LIST_TYPE_LOVE){ + } else if (mListType == Constant.LIST_TYPE_LOVE) { if (mCurrent >= mLoveList.size()) { mCurrent = 0; } - Log.d(TAG, "next: " + mCurrent); saveLoveInfo(mCurrent); mPlayStatusBinder.play(Constant.LIST_TYPE_LOVE); sendBroadcast(new Intent(BroadcastName.LOVE_SONG_CHANGE)); - }else{ + } else { if (mCurrent >= mHistoryList.size()) { mCurrent = 0; } @@ -261,6 +260,7 @@ public class PlayerService extends Service { } public void last() { + sendBroadcast(new Intent(BroadcastName.SONG_PAUSE));//暂停广播 mCurrent = FileHelper.getSong().getCurrent(); mCurrent--; if (mCurrent == -1) { @@ -280,11 +280,11 @@ public class PlayerService extends Service { saveOnlineSongInfo(mCurrent); mPlayStatusBinder.play(mListType); sendBroadcast(new Intent(BroadcastName.ONLINE_ALBUM_SONG_Change));//专辑列表的改变 - } else if(mListType == Constant.LIST_TYPE_LOVE) { + } else if (mListType == Constant.LIST_TYPE_LOVE) { saveLoveInfo(mCurrent); mPlayStatusBinder.play(mListType); sendBroadcast(new Intent(BroadcastName.LOVE_SONG_CHANGE)); - }else{ + } else { saveHistoryInfo(mCurrent); mPlayStatusBinder.play(mListType); } @@ -412,7 +412,7 @@ public class PlayerService extends Service { //保存我的收藏的列表的信息 private void saveHistoryInfo(int current) { - HistorySong historySong=mHistoryList.get(current); + HistorySong historySong = mHistoryList.get(current); Song song = new Song(); song.setCurrent(current); song.setOnlineId(historySong.getSongId()); @@ -427,7 +427,6 @@ public class PlayerService extends Service { //将歌曲保存到最近播放的数据库中 private void saveToHistoryTable() { - Log.d(TAG, "saveToHistoryTable: ture"); final Song song = FileHelper.getSong(); LitePal.where("songId=?", song.getOnlineId()).findAsync(HistorySong.class) @@ -448,8 +447,8 @@ public class PlayerService extends Service { @Override public void onFinish(boolean success) { if (success) { - if(LitePal.findAll(HistorySong.class).size()>Constant.HISTORY_MAX_SIZE){ - LitePal.delete(HistorySong.class,LitePal.findFirst(HistorySong.class).getId()); + if (LitePal.findAll(HistorySong.class).size() > Constant.HISTORY_MAX_SIZE) { + LitePal.delete(HistorySong.class, LitePal.findFirst(HistorySong.class).getId()); } } } diff --git a/app/src/main/java/com/example/musicplayer/util/FileHelper.java b/app/src/main/java/com/example/musicplayer/util/FileHelper.java index f3a5d67..0933628 100644 --- a/app/src/main/java/com/example/musicplayer/util/FileHelper.java +++ b/app/src/main/java/com/example/musicplayer/util/FileHelper.java @@ -55,7 +55,7 @@ public class FileHelper { //写对象流的对象 File userFile = new File(file, "song.txt"); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(userFile)); - oos.writeObject(song); //将Person对象p写入到oos中 + oos.writeObject(song);//将Person对象p写入到oos中 oos.close(); //关闭文件流 } catch (FileNotFoundException e) { // TODO Auto-generated catch block diff --git a/app/src/main/java/com/example/musicplayer/util/RxApiManager.java b/app/src/main/java/com/example/musicplayer/util/RxApiManager.java new file mode 100644 index 0000000..4d7c21c --- /dev/null +++ b/app/src/main/java/com/example/musicplayer/util/RxApiManager.java @@ -0,0 +1,94 @@ +package com.example.musicplayer.util; + +import android.annotation.TargetApi; +import android.os.Build; +import android.support.v4.util.ArrayMap; +import android.util.Log; + + +import com.example.musicplayer.callback.RxActionManager; + +import org.reactivestreams.Subscription; + +import java.util.Set; + +import io.reactivex.disposables.Disposable; + + +/** + * Created by 残渊 on 2018/12/5. + */ + +public class RxApiManager implements RxActionManager { + private static final String TAG="RxApiManager"; + + private static RxApiManager sInstance = null; + + private ArrayMap maps; + + public static RxApiManager get() { + + if (sInstance == null) { + synchronized (RxApiManager.class) { + if (sInstance == null) { + sInstance = new RxApiManager(); + } + } + } + return sInstance; + } + + @TargetApi(Build.VERSION_CODES.KITKAT) + private RxApiManager() { + maps = new ArrayMap<>(); + } + + @TargetApi(Build.VERSION_CODES.KITKAT) + @Override + public void add(Object tag, Disposable disposable) { + maps.put(tag, disposable); + } + + @TargetApi(Build.VERSION_CODES.KITKAT) + @Override + public void remove(Object tag) { + if (!maps.isEmpty()) { + maps.remove(tag); + } + } + + @TargetApi(Build.VERSION_CODES.KITKAT) + public void removeAll() { + if (!maps.isEmpty()) { + maps.clear(); + } + } + + @TargetApi(Build.VERSION_CODES.KITKAT) + @Override public void cancel(Object tag) { + if (maps.isEmpty()) { + return; + } + if (maps.get(tag) == null) { + return; + } + if (!maps.get(tag).isDisposed()) { + Log.d(TAG, "cancel: "+tag); + maps.get(tag).dispose(); + maps.remove(tag); + } + } + + @TargetApi(Build.VERSION_CODES.KITKAT) + @Override public void cancelAll() { + if (maps.isEmpty()) { + return; + } + Set keys = maps.keySet(); + for (Object apiKey : keys) { + cancel(apiKey); + } + removeAll(); + } +} + diff --git a/app/src/main/java/com/example/musicplayer/view/AlbumSongFragment.java b/app/src/main/java/com/example/musicplayer/view/AlbumSongFragment.java index 41afe71..1c8c9d7 100644 --- a/app/src/main/java/com/example/musicplayer/view/AlbumSongFragment.java +++ b/app/src/main/java/com/example/musicplayer/view/AlbumSongFragment.java @@ -19,6 +19,7 @@ import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.TextView; import com.example.musicplayer.R; @@ -35,8 +36,10 @@ import com.example.musicplayer.presenter.AlbumSongPresenter; import com.example.musicplayer.service.PlayerService; import com.example.musicplayer.util.CommonUtil; import com.example.musicplayer.util.FileHelper; +import com.example.musicplayer.util.RxApiManager; import com.github.florent37.materialviewpager.MaterialViewPagerHelper; import com.github.florent37.materialviewpager.header.MaterialViewPagerHeaderDecorator; +import com.wang.avi.AVLoadingIndicatorView; import org.litepal.LitePal; @@ -64,6 +67,12 @@ public class AlbumSongFragment extends Fragment implements IAlbumSongContract.Vi private String mPublicTime; private String mDesc; + //用来判断网络问题及加载问题 + private AVLoadingIndicatorView mLoading; + private TextView mLoadingTv; + private ImageView mNetworkErrorIv; + + private List mSongsList; private RecyclerView mRecycle; @@ -94,6 +103,9 @@ public class AlbumSongFragment extends Fragment implements IAlbumSongContract.Vi if (mType == ALBUM_SONG) { view = inflater.inflate(R.layout.fragment_album_recycler, container, false); mRecycle = view.findViewById(R.id.recycler_song_list); + mLoading = view.findViewById(R.id.avi); + mLoadingTv = view.findViewById(R.id.tv_loading); + mNetworkErrorIv = view.findViewById(R.id.iv_network_error); LitePal.getDatabase(); } else { view = inflater.inflate(R.layout.fragment_album_song, container, false); @@ -130,9 +142,9 @@ public class AlbumSongFragment extends Fragment implements IAlbumSongContract.Vi } @Override - public void onDestroy(){ - super.onDestroy(); - getActivity().unregisterReceiver(albumSongChangeReceiver); + public void onDestroyView(){ + RxApiManager.get().cancel(Constant.ALBUM); + super.onDestroyView(); } private void getBundle(){ @@ -198,9 +210,24 @@ public class AlbumSongFragment extends Fragment implements IAlbumSongContract.Vi mPublicTimeTv.setText(mPublicTime); } + @Override + public void showLoading() { + mLoading.show(); + } + + @Override + public void hideLoading() { + mLoading.hide(); + mLoadingTv.setVisibility(View.GONE); + mRecycle.setVisibility(View.VISIBLE); + mNetworkErrorIv.setVisibility(View.GONE); + } + @Override public void showNetError() { - CommonUtil.showToast(getActivity(),"网络错误"); + mLoadingTv.setVisibility(View.GONE); + mLoading.hide(); + mNetworkErrorIv.setVisibility(View.VISIBLE); } class AlbumSongChangeReceiver extends BroadcastReceiver { diff --git a/app/src/main/java/com/example/musicplayer/view/LocalMusicFragment.java b/app/src/main/java/com/example/musicplayer/view/LocalMusicFragment.java index cbda372..9a83d10 100644 --- a/app/src/main/java/com/example/musicplayer/view/LocalMusicFragment.java +++ b/app/src/main/java/com/example/musicplayer/view/LocalMusicFragment.java @@ -16,7 +16,9 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; +import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.Toast; import com.example.musicplayer.R; @@ -54,7 +56,7 @@ public class LocalMusicFragment extends Fragment implements ILocalMusicContract. private ImageView mFindLocalMusicIv; private ImageView mBackIv; - private ViewStub mEmptyViewStub; + private FrameLayout mEmptyViewLinear; private ServiceConnection connection = new ServiceConnection() { @Override @@ -76,22 +78,23 @@ public class LocalMusicFragment extends Fragment implements ILocalMusicContract. mRecycler = mView.findViewById(R.id.recycler_song_list); mFindLocalMusicIv = mView.findViewById(R.id.iv_find_local_song); mBackIv = mView.findViewById(R.id.iv_back); - mEmptyViewStub = mView.findViewById(R.id.stub_empty); + mEmptyViewLinear = mView.findViewById(R.id.linear_empty); return mView; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - intentFilter=new IntentFilter(); + intentFilter = new IntentFilter(); intentFilter.addAction(BroadcastName.LOCAL_SONG_CHANGE_LIST); - songChangeReceiver=new SongChangeLocalMusicReceiver(); - getActivity().registerReceiver(songChangeReceiver,intentFilter); + songChangeReceiver = new SongChangeLocalMusicReceiver(); + getActivity().registerReceiver(songChangeReceiver, intentFilter); initView(); setOnClickListener(); } + @Override - public void onDestroy(){ + public void onDestroy() { super.onDestroy(); getActivity().unbindService(connection); getActivity().unregisterReceiver(songChangeReceiver); @@ -101,7 +104,7 @@ public class LocalMusicFragment extends Fragment implements ILocalMusicContract. LitePal.getDatabase(); //创建数据库 mLocalSongsList = new ArrayList<>(); layoutManager = new LinearLayoutManager(mView.getContext()); - songAdapter = new SongAdapter(mView.getContext(),mLocalSongsList); + songAdapter = new SongAdapter(mView.getContext(), mLocalSongsList); mPresenter = new LocalMusicPresenter(); mPresenter.attachView(this); //与Presenter建立关系 //启动服务 @@ -109,22 +112,21 @@ public class LocalMusicFragment extends Fragment implements ILocalMusicContract. getActivity().bindService(playIntent, connection, Context.BIND_AUTO_CREATE); mLocalSongsList = LitePal.findAll(LocalSong.class); - Log.d(TAG, "initView: "+mLocalSongsList.size()); - if(mLocalSongsList.size()==0){ + if (mLocalSongsList.size() == 0) { mRecycler.setVisibility(View.GONE); - mEmptyViewStub.setVisibility(View.VISIBLE); - }else{ + mEmptyViewLinear.setVisibility(View.VISIBLE); + } else { mRecycler.setVisibility(View.VISIBLE); - mEmptyViewStub.setVisibility(View.GONE); + mEmptyViewLinear.setVisibility(View.GONE); mRecycler.setLayoutManager(layoutManager); //令recyclerView定位到当前播放的位置 - songAdapter = new SongAdapter(mView.getContext(),mLocalSongsList); + songAdapter = new SongAdapter(mView.getContext(), mLocalSongsList); mRecycler.setAdapter(songAdapter); - if(FileHelper.getSong()!=null) { - layoutManager.scrollToPositionWithOffset(FileHelper.getSong().getCurrent()-4, mRecycler.getHeight()); + if (FileHelper.getSong() != null) { + layoutManager.scrollToPositionWithOffset(FileHelper.getSong().getCurrent() - 4, mRecycler.getHeight()); } } @@ -172,15 +174,24 @@ public class LocalMusicFragment extends Fragment implements ILocalMusicContract. getActivity().runOnUiThread(new Runnable() { @Override public void run() { + mLocalSongsList.clear(); mLocalSongsList.addAll(mp3InfoList); - mRecycler.setLayoutManager(layoutManager); - //令recyclerView定位到当前播放的位置 - songAdapter = new SongAdapter(mView.getContext(),mLocalSongsList); - mRecycler.setAdapter(songAdapter); - CommonUtil.showToast(getActivity(),"成功导入本地音乐"); - mPresenter.saveSong(mp3InfoList);//保存到数据库中 - if(FileHelper.getSong()!=null) { - layoutManager.scrollToPositionWithOffset(FileHelper.getSong().getCurrent()-4, mRecycler.getHeight()); + if (mLocalSongsList.size() == 0) { + mRecycler.setVisibility(View.GONE); + mEmptyViewLinear.setVisibility(View.VISIBLE); + } else { + mRecycler.setVisibility(View.VISIBLE); + mEmptyViewLinear.setVisibility(View.GONE); + mRecycler.setLayoutManager(layoutManager); + //令recyclerView定位到当前播放的位置 + songAdapter = new SongAdapter(mView.getContext(), mLocalSongsList); + mRecycler.setAdapter(songAdapter); + setOnClickListener(); + CommonUtil.showToast(getActivity(), "成功导入本地音乐"); + mPresenter.saveSong(mp3InfoList);//保存到数据库中 + if (FileHelper.getSong() != null) { + layoutManager.scrollToPositionWithOffset(FileHelper.getSong().getCurrent() - 4, mRecycler.getHeight()); + } } } }); @@ -192,8 +203,8 @@ public class LocalMusicFragment extends Fragment implements ILocalMusicContract. @Override public void onReceive(Context context, Intent intent) { songAdapter.notifyDataSetChanged(); - if(FileHelper.getSong()!=null) { - layoutManager.scrollToPositionWithOffset(FileHelper.getSong().getCurrent()+4, mRecycler.getHeight()); + if (FileHelper.getSong() != null) { + layoutManager.scrollToPositionWithOffset(FileHelper.getSong().getCurrent() + 4, mRecycler.getHeight()); } } } diff --git a/app/src/main/java/com/example/musicplayer/view/MainActivity.java b/app/src/main/java/com/example/musicplayer/view/MainActivity.java index f61540d..ebf5daf 100644 --- a/app/src/main/java/com/example/musicplayer/view/MainActivity.java +++ b/app/src/main/java/com/example/musicplayer/view/MainActivity.java @@ -37,6 +37,7 @@ import com.example.musicplayer.service.PlayerService; import com.example.musicplayer.util.CommonUtil; import com.example.musicplayer.util.FileHelper; import com.example.musicplayer.util.MediaUtil; +import com.example.musicplayer.util.RxApiManager; import org.litepal.LitePal; @@ -92,21 +93,22 @@ public class MainActivity extends AppCompatActivity { songChangeReceiver = new SongChangeReceiver(); registerReceiver(songChangeReceiver, intentFilter); LitePal.getDatabase(); - + //启动服务 + Intent playIntent = new Intent(MainActivity.this, PlayerService.class); + bindService(playIntent, connection, Context.BIND_AUTO_CREATE); initView(); - onClick(); } private void initView() { mSong = FileHelper.getSong(); - Log.d(TAG, "jsyjst: " + mSong.toString()); mSongNameTv = findViewById(R.id.tv_song_name); mSingerTv = findViewById(R.id.tv_singer); mLinear = findViewById(R.id.linear_player); mSeekBar = findViewById(R.id.sb_progress); mNextIv = findViewById(R.id.song_next); mCoverIv = findViewById(R.id.circle_img); + mPlayerBtn = findViewById(R.id.btn_player); //设置属性动画 mCircleAnimator = ObjectAnimator.ofFloat(mCoverIv, "rotation", 0.0f, 360.0f); mCircleAnimator.setDuration(30000); @@ -116,11 +118,6 @@ public class MainActivity extends AppCompatActivity { if (mSong.getSongName() != null) { - //启动服务 - Intent playIntent = new Intent(MainActivity.this, PlayerService.class); - bindService(playIntent, connection, Context.BIND_AUTO_CREATE); - Log.d(TAG, "------initView:bindService "); - mLinear.setVisibility(View.VISIBLE); mSongNameTv.setText(mSong.getSongName()); mSingerTv.setText(mSong.getSinger()); @@ -135,12 +132,20 @@ public class MainActivity extends AppCompatActivity { .apply(RequestOptions.errorOf(R.drawable.welcome)) .into(mCoverIv); } - + onClick(); } else { - mLinear.setVisibility(View.GONE); + mSongNameTv.setText("心渊音乐"); + mSingerTv.setText("袁健策 3117004905"); + mCoverIv.setImageResource(R.drawable.jay); + mLinear.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + CommonUtil.showToast(MainActivity.this, "开启你的音乐之旅吧"); + } + }); } - mPlayerBtn = findViewById(R.id.btn_player); + addMainFragment(); } @@ -181,8 +186,6 @@ public class MainActivity extends AppCompatActivity { time = mMediaPlayer.getCurrentPosition(); mPlayStatusBinder.pause(); flag = true; - mPlayerBtn.setSelected(false); - mCircleAnimator.pause(); } else if (flag) { mPlayStatusBinder.resume(); flag = false; @@ -191,10 +194,6 @@ public class MainActivity extends AppCompatActivity { } else { isSeek = false; } - mCircleAnimator.resume(); - mPlayerBtn.setSelected(true); - mSeekBarThread = new Thread(new SeekBarThread()); - mSeekBarThread.start(); } else { if (FileHelper.getSong().isOnline()) { mPlayStatusBinder.playOnline(); @@ -202,9 +201,6 @@ public class MainActivity extends AppCompatActivity { mPlayStatusBinder.play(FileHelper.getSong().getListType()); } mMediaPlayer.seekTo((int) mSong.getCurrentTime()); - mCircleAnimator.start(); - mPlayerBtn.setSelected(true); - seekBarStart(); } } }); @@ -259,14 +255,13 @@ public class MainActivity extends AppCompatActivity { public void onDestroy() { unbindService(connection); unregisterReceiver(songChangeReceiver); - if(mSeekBarThread!=null) mSeekBarThread.interrupt(); + if (mSeekBarThread != null) mSeekBarThread.interrupt(); Song song = FileHelper.getSong(); song.setCurrentTime(mPlayStatusBinder.getCurrentTime()); - Log.d(TAG, "onServiceDisconnected: " + song.getCurrentTime()); FileHelper.saveSong(song); + RxApiManager.get().cancelAll(); super.onDestroy(); - } private void seekBarStart() { @@ -277,7 +272,7 @@ public class MainActivity extends AppCompatActivity { class SeekBarThread implements Runnable { @Override public void run() { - if (mPlayStatusBinder!=null) { + if (mPlayStatusBinder != null) { while (!isChange && mPlayStatusBinder.isPlaying()) { mSeekBar.setProgress((int) mPlayStatusBinder.getCurrentTime()); try { @@ -297,32 +292,35 @@ public class MainActivity extends AppCompatActivity { String action = intent.getAction(); mSong = FileHelper.getSong(); - mSongNameTv.setText(mSong.getSongName()); - mSingerTv.setText(mSong.getSinger()); - mSeekBar.setMax((int) mSong.getDuration()); - - if (!mSong.isOnline()) { - FileHelper.setSingerImg(MainActivity.this, mSong.getSinger(), mCoverIv); - } else { - Glide.with(MainActivity.this) - .load(mSong.getImgUrl()) - .apply(RequestOptions.placeholderOf(R.drawable.welcome)) - .apply(RequestOptions.errorOf(R.drawable.welcome)) - .into(mCoverIv); - } - if (action.equals(BroadcastName.SONG_PAUSE)) { + onClick(); + if (action.equals(BroadcastName.ONLINE_SONG_ERROR)) { + CommonUtil.showToast(MainActivity.this, "抱歉,该歌曲暂无版权,搜搜其他歌曲吧"); + } else if (action.equals(BroadcastName.SONG_PAUSE)) { mPlayerBtn.setSelected(false); mCircleAnimator.pause(); } else if (action.equals(BroadcastName.SONG_RESUME)) { mPlayerBtn.setSelected(true); mCircleAnimator.resume(); seekBarStart(); - - } else { + } else if (action.equals(BroadcastName.SONG_CHANGE)) { + mSong = FileHelper.getSong(); + mSongNameTv.setText(mSong.getSongName()); + mSingerTv.setText(mSong.getSinger()); + Log.d(TAG, "onReceive: " + mSong.getDuration()); + mSeekBar.setMax((int) mSong.getDuration()); mPlayerBtn.setSelected(true); mCircleAnimator.start(); seekBarStart(); } + if (!mSong.isOnline()) { + FileHelper.setSingerImg(MainActivity.this, mSong.getSinger(), mCoverIv); + } else { + Glide.with(MainActivity.this) + .load(mSong.getImgUrl()) + .apply(RequestOptions.placeholderOf(R.drawable.welcome)) + .apply(RequestOptions.errorOf(R.drawable.welcome)) + .into(mCoverIv); + } } } } diff --git a/app/src/main/java/com/example/musicplayer/view/MainFragment.java b/app/src/main/java/com/example/musicplayer/view/MainFragment.java index f552da6..79816f6 100644 --- a/app/src/main/java/com/example/musicplayer/view/MainFragment.java +++ b/app/src/main/java/com/example/musicplayer/view/MainFragment.java @@ -13,22 +13,17 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; -import android.widget.ExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.LinearLayout; import android.widget.TextView; import com.example.musicplayer.R; import com.example.musicplayer.adapter.ExpandableListViewAdapter; -import com.example.musicplayer.adapter.HistoryAdapter; import com.example.musicplayer.constant.BroadcastName; -import com.example.musicplayer.entiy.Album; import com.example.musicplayer.entiy.AlbumCollection; import com.example.musicplayer.entiy.HistorySong; import com.example.musicplayer.entiy.LocalSong; import com.example.musicplayer.entiy.Love; -import com.example.musicplayer.util.CommonUtil; import com.example.musicplayer.widget.MyListView; import org.litepal.LitePal; @@ -46,19 +41,13 @@ public class MainFragment extends Fragment { private MyListView myListView; private ExpandableListViewAdapter mAdapter; private LinearLayout mLocalMusicLinear, mCollectionLinear, mHistoryMusicLinear; - private Button playerBtn; private TextView mLocalMusicNum, mLoveMusicNum, mHistoryMusicNum; private TextView mSeekBtn; private List> mAlbumCollectionList; private List mLoveAlbumList; - private boolean oneExpand; private boolean twoExpand; private String[] mGroupStrings = {"自建歌单", "收藏歌单"}; - private String[][] mSongStrings = { - {"我喜欢"}, - {"Jay", "魔杰座"} - }; //注册广播 private IntentFilter intentFilter; private SongChangeReceiver songChangeReceiver; @@ -70,7 +59,6 @@ public class MainFragment extends Fragment { View view = inflater.inflate(R.layout.fragment_main, container, false); mLocalMusicLinear = view.findViewById(R.id.linear_local_music); mCollectionLinear = view.findViewById(R.id.linear_collection); - playerBtn = view.findViewById(R.id.btn_player); mFunctionLinear = view.findViewById(R.id.linear_function); mHistoryMusicLinear = view.findViewById(R.id.linear_history); //获取焦点 @@ -87,6 +75,17 @@ public class MainFragment extends Fragment { public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); + //注册广播 + intentFilter = new IntentFilter(); + intentFilter.addAction(BroadcastName.SONG_CHANGE); + intentFilter.addAction(BroadcastName.COLLECTION_ALBUM_CHANGE); + songChangeReceiver = new SongChangeReceiver(); + getActivity().registerReceiver(songChangeReceiver, intentFilter); + + showAlbumList(); + onClick(); + } + private void showAlbumList(){ mLoveAlbumList = new ArrayList<>(); mAlbumCollectionList = new ArrayList<>(); AlbumCollection albumCollection = new AlbumCollection(); @@ -97,13 +96,6 @@ public class MainFragment extends Fragment { mAlbumCollectionList.add(orderCollection(LitePal.findAll(AlbumCollection.class))); mAdapter = new ExpandableListViewAdapter(getActivity(), mGroupStrings, mAlbumCollectionList); myListView.setAdapter(mAdapter); - //注册广播 - intentFilter = new IntentFilter(); - intentFilter.addAction(BroadcastName.SONG_CHANGE); - intentFilter.addAction(BroadcastName.COLLECTION_ALBUM_CHANGE); - songChangeReceiver = new SongChangeReceiver(); - getActivity().registerReceiver(songChangeReceiver, intentFilter); - onClick(); } @Override @@ -116,7 +108,6 @@ public class MainFragment extends Fragment { public void onResume() { super.onResume(); showMusicNum(); - Log.d(TAG, "onResume: true"); } private void onClick() { @@ -150,9 +141,7 @@ public class MainFragment extends Fragment { myListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() { @Override public void onGroupExpand(int groupPosition) { - if (groupPosition == 0) { - oneExpand = true; - } else if (groupPosition == 1) { + if (groupPosition == 1) { twoExpand = true; } } @@ -160,9 +149,7 @@ public class MainFragment extends Fragment { myListView.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() { @Override public void onGroupCollapse(int groupPosition) { - if (groupPosition == 0) { - oneExpand = false; - } else if (groupPosition == 1) { + if (groupPosition == 1) { twoExpand = false; } } @@ -173,13 +160,15 @@ public class MainFragment extends Fragment { return false; } }); - + //二级列表的item点击效果 mAdapter.setOnChildItemClickListener(new ExpandableListViewAdapter.OnChildItemClickListener() { @Override public void onClick(int groupPosition, int childPosition) { + //一级列表的第一个默认为我喜欢的歌单,故点击后跳转到我的收藏界面 if (groupPosition == 0 && childPosition == 0) { replaceFragment(new CollectionFragment()); } else if (groupPosition == 1) { + //其他的列表都是我的收藏的列表,故跳转到专辑详细fragment AlbumCollection albumCollection = mAlbumCollectionList.get(groupPosition).get(childPosition); replaceFragment(AlbumContentFragment.newInstance( albumCollection.getAlbumId(), @@ -207,13 +196,14 @@ public class MainFragment extends Fragment { transaction.commit(); } + //显示数目 private void showMusicNum() { - mLoveMusicNum.setText("" + LitePal.findAll(LocalSong.class).size()); + mLocalMusicNum.setText("" + LitePal.findAll(LocalSong.class).size()); mLoveMusicNum.setText("" + LitePal.findAll(Love.class).size()); mHistoryMusicNum.setText("" + LitePal.findAll(HistorySong.class).size()); - } + //使数据库中的列表逆序排列 private List orderCollection(List tempList) { List mAlbumCollectionList = new ArrayList<>(); for (int i = tempList.size() - 1; i >= 0; i--) { @@ -222,6 +212,7 @@ public class MainFragment extends Fragment { return mAlbumCollectionList; } + //收藏和最近播放变化的广播接收器 private class SongChangeReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { @@ -232,6 +223,7 @@ public class MainFragment extends Fragment { mAlbumCollectionList.clear(); mAlbumCollectionList.add(mLoveAlbumList); mAlbumCollectionList.add(orderCollection(LitePal.findAll(AlbumCollection.class))); + //根据之前的状态,进行展开和收缩,从而达到更新列表的功能 if (twoExpand) { myListView.collapseGroup(1); myListView.expandGroup(1); diff --git a/app/src/main/java/com/example/musicplayer/view/PlayActivity.java b/app/src/main/java/com/example/musicplayer/view/PlayActivity.java index ad1ff17..a8c3cd7 100644 --- a/app/src/main/java/com/example/musicplayer/view/PlayActivity.java +++ b/app/src/main/java/com/example/musicplayer/view/PlayActivity.java @@ -18,6 +18,7 @@ import android.media.MediaPlayer; import android.os.Handler; import android.os.IBinder; import android.os.Message; +import android.provider.ContactsContract; import android.support.annotation.Nullable; import android.transition.Slide; import android.util.Log; @@ -52,6 +53,7 @@ import com.example.musicplayer.util.DisplayUtil; import com.example.musicplayer.util.FastBlurUtil; import com.example.musicplayer.util.FileHelper; import com.example.musicplayer.util.MediaUtil; +import com.example.musicplayer.util.RxApiManager; import com.example.musicplayer.widget.BackgroundAnimationRelativeLayout; import com.example.musicplayer.widget.DiscView; @@ -59,8 +61,6 @@ import org.litepal.LitePal; import java.util.List; -import static com.example.musicplayer.view.AlbumSongFragment.IS_ONLINE_ALBUM; - /** * 播放界面 */ @@ -80,6 +80,7 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { private MediaPlayer mMediaPlayer; private TextView mSongTv; // + private ImageView mBackIv; private TextView mSingerTv; private Button mPlayBtn; private Button mLastBtn; @@ -111,6 +112,13 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { @Override public void onServiceConnected(ComponentName name, IBinder service) { mPlayStatusBinder = (PlayerService.PlayStatusBinder) service; + //缓存进度条 + mPlayStatusBinder.getMediaPlayer().setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { + @Override + public void onBufferingUpdate(MediaPlayer mp, int percent) { + mSeekBar.setSecondaryProgress(percent*mSeekBar.getProgress()); + } + }); isOnline = FileHelper.getSong().isOnline(); if (isOnline) { mGetImgAndLrcBtn.setVisibility(View.GONE); @@ -138,7 +146,6 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { public void handleMessage(Message msg) { super.handleMessage(msg); if (!isChange) { - Log.d(TAG, "handleMessage: send"); mSeekBar.setProgress((int) mPlayStatusBinder.getCurrentTime()); mCurrentTimeTv.setText(MediaUtil.formatTime(mSeekBar.getProgress())); startUpdateSeekBarProgress(); @@ -182,7 +189,7 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { mLastBtn = findViewById(R.id.btn_last); mNextBtn = findViewById(R.id.next); mGetImgAndLrcBtn = findViewById(R.id.btn_get_img_lrc); - + mBackIv = findViewById(R.id.iv_back); mSeekBar = findViewById(R.id.seek); mDurationTimeTv = findViewById(R.id.tv_duration_time); mCurrentTimeTv = findViewById(R.id.tv_current_time); @@ -202,6 +209,7 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { mCurrentTimeTv.setText(MediaUtil.formatTime(mSong.getCurrentTime())); mSeekBar.setMax((int) mSong.getDuration()); mSeekBar.setProgress((int) mSong.getCurrentTime()); + mPresenter.queryLove(mSong.getOnlineId()); //查找歌曲是否为我喜欢的歌曲 if (mPlayStatus == PlayerStatus.PLAY) { @@ -258,7 +266,12 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { @Override protected void onClick() { - + mBackIv.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); mGetImgAndLrcBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -482,6 +495,15 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { mPlayBtn.setSelected(true); mSeekBar.setMax((int) mSong.getDuration()); startUpdateSeekBarProgress(); + //缓存进度条 + mPlayStatusBinder.getMediaPlayer().setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { + @Override + public void onBufferingUpdate(MediaPlayer mp, int percent) { + Log.d(TAG, "onBufferingUpdate: "+percent); + mSeekBar.setSecondaryProgress(percent*mSeekBar.getProgress()); + } + }); + mPresenter.queryLove(mSong.getOnlineId()); //查找歌曲是否为我喜欢的歌曲 if (mSong.isOnline()) { setSingerImg(mSong.getImgUrl()); } else { @@ -541,7 +563,7 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { unbindService(connection); unregisterReceiver(songChangeReceiver); stopUpdateSeekBarProgress(); - + RxApiManager.get().cancel(Constant.LOCAL_IMG); } } diff --git a/app/src/main/java/com/example/musicplayer/view/SearchContentFragment.java b/app/src/main/java/com/example/musicplayer/view/SearchContentFragment.java index c82b807..d3354d9 100644 --- a/app/src/main/java/com/example/musicplayer/view/SearchContentFragment.java +++ b/app/src/main/java/com/example/musicplayer/view/SearchContentFragment.java @@ -16,6 +16,8 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; import com.example.musicplayer.R; import com.example.musicplayer.adapter.SearchContentAdapter; @@ -29,10 +31,12 @@ import com.example.musicplayer.presenter.SearchContentPresenter; import com.example.musicplayer.service.PlayerService; import com.example.musicplayer.util.CommonUtil; import com.example.musicplayer.util.FileHelper; +import com.example.musicplayer.util.RxApiManager; import com.github.jdsjlzx.interfaces.OnLoadMoreListener; import com.github.jdsjlzx.interfaces.OnNetWorkErrorListener; import com.github.jdsjlzx.recyclerview.LRecyclerView; import com.github.jdsjlzx.recyclerview.LRecyclerViewAdapter; +import com.wang.avi.AVLoadingIndicatorView; import java.util.ArrayList; import java.util.List; @@ -48,8 +52,8 @@ public class SearchContentFragment extends Fragment implements ISearchContentCon public static final String IS_ONLINE = "online"; private int mOffset = 1; //用于翻页搜索 - private String mAlbumName,mSingerName,mAlbumPic,mPublicTime; - + private String mAlbumName, mSingerName, mAlbumPic, mPublicTime; + private SongFinishReceiver songFinishReceiver; private SearchContentPresenter mPresenter; private LRecyclerView mRecycler; private LinearLayoutManager manager; @@ -59,6 +63,10 @@ public class SearchContentFragment extends Fragment implements ISearchContentCon private IntentFilter intentFilter; private LRecyclerViewAdapter mLRecyclerViewAdapter;//下拉刷新 + private AVLoadingIndicatorView mLoading; + private TextView mLoadingTv; + private ImageView mBackgroundIv; + private ImageView mNetworkErrorIv; private Bundle mBundle; private String mSeek; @@ -89,6 +97,10 @@ public class SearchContentFragment extends Fragment implements ISearchContentCon } mRecycler = view.findViewById(R.id.recycler_song_list); + mLoading = view.findViewById(R.id.avi); + mLoadingTv = view.findViewById(R.id.tv_loading); + mBackgroundIv = view.findViewById(R.id.iv_background); + mNetworkErrorIv = view.findViewById(R.id.iv_network_error); mPresenter = new SearchContentPresenter(); mPresenter.attachView(this); if (mType.equals("song")) { @@ -110,7 +122,8 @@ public class SearchContentFragment extends Fragment implements ISearchContentCon intentFilter = new IntentFilter(); intentFilter.addAction(BroadcastName.ONLINE_SONG_FINISH); intentFilter.addAction(BroadcastName.ONLINE_ALBUM_SONG_Change); - SongFinishReceiver songFinishReceiver = new SongFinishReceiver(); + intentFilter.addAction(BroadcastName.ONLINE_SONG_ERROR); + songFinishReceiver = new SongFinishReceiver(); getActivity().registerReceiver(songFinishReceiver, intentFilter); //启动服务 @@ -119,10 +132,21 @@ public class SearchContentFragment extends Fragment implements ISearchContentCon } + @Override - public void onDestroy(){ + public void onDestroy() { super.onDestroy(); getActivity().unbindService(connection); + getActivity().unregisterReceiver(songFinishReceiver); + } + @Override + public void onDestroyView(){ + Log.d(TAG, "onDestroyView: true"); + RxApiManager.get().cancel(Constant.SEARCH_SONG); + RxApiManager.get().cancel(Constant.SEARCH_ALBUM); + RxApiManager.get().cancel(Constant.SEARCH_ALBUM_MORE); + RxApiManager.get().cancel(Constant.SEARCH_SONG_MORE); + super.onDestroyView(); } @@ -178,8 +202,8 @@ public class SearchContentFragment extends Fragment implements ISearchContentCon Log.d(TAG, "onLoadMore: mOffset=" + mOffset); if (mType.equals("song")) { mPresenter.searchMore(mSeek, mOffset); - }else{ - mPresenter.searchAlbumMore(mSeek,mOffset); + } else { + mPresenter.searchAlbumMore(mSeek, mOffset); } } }); @@ -201,7 +225,7 @@ public class SearchContentFragment extends Fragment implements ISearchContentCon @Override public void reload() { mOffset += 1; - mPresenter.searchMore(mSeek, mOffset); + mPresenter.searchMore(mSeek, mOffset); } }); } @@ -235,6 +259,28 @@ public class SearchContentFragment extends Fragment implements ISearchContentCon CommonUtil.showToast(getActivity(), "获取专辑信息失败"); } + @Override + public void showLoading() { + mLoading.show(); + } + + @Override + public void hideLoading() { + mRecycler.setVisibility(View.VISIBLE); + mLoading.hide(); + mLoadingTv.setVisibility(View.GONE); + mBackgroundIv.setVisibility(View.GONE); + mNetworkErrorIv.setVisibility(View.GONE); + } + + @Override + public void showNetError() { + mRecycler.setVisibility(View.GONE); + mLoading.setVisibility(View.GONE); + mLoadingTv.setVisibility(View.GONE); + mNetworkErrorIv.setVisibility(View.VISIBLE); + } + /** * 构造带参数的fragment * @@ -253,17 +299,22 @@ public class SearchContentFragment extends Fragment implements ISearchContentCon @Override public void onReceive(Context context, Intent intent) { - Log.d(TAG, "onReceive: "+intent.getAction()); - mAdapter.notifyDataSetChanged(); + Log.d(TAG, "onReceive: " + intent.getAction()); + String action = intent.getAction(); + if (action.equals(BroadcastName.ONLINE_SONG_ERROR)) { + CommonUtil.showToast(getActivity(), "抱歉该歌曲暂没有版权,搜搜其他歌曲吧"); + } else { + mAdapter.notifyDataSetChanged(); + } } } - public void toAlbumContentFragment(Album.DataBean album){ + public void toAlbumContentFragment(Album.DataBean album) { FragmentManager manager = getActivity().getSupportFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); transaction.setCustomAnimations(R.anim.fragment_in, R.anim.fragment_out, R.anim.slide_in_right, R.anim.slide_out_right); - transaction.add(R.id.fragment_container,AlbumContentFragment. - newInstance(album.getAlbumMID(),album.getAlbumName(),album.getAlbumPic(),album.getSingerName(),album.getPublicTime())); + transaction.add(R.id.fragment_container, AlbumContentFragment. + newInstance(album.getAlbumMID(), album.getAlbumName(), album.getAlbumPic(), album.getSingerName(), album.getPublicTime())); transaction.hide(this); //将事务提交到返回栈 transaction.addToBackStack(null); diff --git a/app/src/main/java/com/example/musicplayer/view/SearchFragment.java b/app/src/main/java/com/example/musicplayer/view/SearchFragment.java index 3e875e0..a48073d 100644 --- a/app/src/main/java/com/example/musicplayer/view/SearchFragment.java +++ b/app/src/main/java/com/example/musicplayer/view/SearchFragment.java @@ -52,6 +52,9 @@ public class SearchFragment extends Fragment { public void onClick(View v) { CommonUtil.closeKeybord(mSeekEdit, getActivity()); mSeekEdit.setCursorVisible(false);//隐藏光标 + if(mSeekEdit.getText().toString().trim().length()==0){ + mSeekEdit.setText(mSeekEdit.getHint().toString().trim()); + } saveDatabase(mSeekEdit.getText().toString()); replaceFragment(ContentFragment.newInstance(mSeekEdit.getText().toString())); } diff --git a/app/src/main/res/drawable-xxhdpi/empty_song.png b/app/src/main/res/drawable-xxhdpi/empty_song.png new file mode 100644 index 0000000..df6ee22 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/empty_song.png differ diff --git a/app/src/main/res/drawable-xxhdpi/network_error.jpg b/app/src/main/res/drawable-xxhdpi/network_error.jpg new file mode 100644 index 0000000..00c661e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/network_error.jpg differ diff --git a/app/src/main/res/drawable/seekbar_bg.xml b/app/src/main/res/drawable/seekbar_bg.xml index 671f87d..583a5b8 100644 --- a/app/src/main/res/drawable/seekbar_bg.xml +++ b/app/src/main/res/drawable/seekbar_bg.xml @@ -3,7 +3,7 @@ - + diff --git a/app/src/main/res/drawable/selector_love.xml b/app/src/main/res/drawable/selector_love.xml index b20a0b9..4df8cf1 100644 --- a/app/src/main/res/drawable/selector_love.xml +++ b/app/src/main/res/drawable/selector_love.xml @@ -1,6 +1,6 @@ + - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_play.xml b/app/src/main/res/layout/activity_play.xml index 4dcf095..8f06eee 100644 --- a/app/src/main/res/layout/activity_play.xml +++ b/app/src/main/res/layout/activity_play.xml @@ -48,7 +48,7 @@ android:ellipsize="end" android:singleLine="true" android:paddingEnd="20dp" - android:textColor="@color/white_easy" /> + android:textColor="@color/white_blue" /> diff --git a/app/src/main/res/layout/activity_welcome.xml b/app/src/main/res/layout/activity_welcome.xml index f1e3a6d..c914ab5 100644 --- a/app/src/main/res/layout/activity_welcome.xml +++ b/app/src/main/res/layout/activity_welcome.xml @@ -1,34 +1,64 @@ + android:background="@drawable/welcome" + android:orientation="horizontal"> + - + + + android:gravity="center_horizontal"> + + + + + - + android:layout_gravity="center_horizontal" + android:layout_below="@+id/iv_icon" + android:textColor="@color/white" + android:textSize="16sp" + android:text="袁健策版权所有@2018"/> + diff --git a/app/src/main/res/layout/empty_song.xml b/app/src/main/res/layout/empty_song.xml index 29774b2..970b7fb 100644 --- a/app/src/main/res/layout/empty_song.xml +++ b/app/src/main/res/layout/empty_song.xml @@ -1,23 +1,23 @@ - + + android:textColor="@color/player"/> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_album_recycler.xml b/app/src/main/res/layout/fragment_album_recycler.xml index 4ed0da9..5441b22 100644 --- a/app/src/main/res/layout/fragment_album_recycler.xml +++ b/app/src/main/res/layout/fragment_album_recycler.xml @@ -1,22 +1,67 @@ - + + + + - - + + + android:layout_height="match_parent"> + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_local_music.xml b/app/src/main/res/layout/fragment_local_music.xml index 23bfda9..2c1cf89 100644 --- a/app/src/main/res/layout/fragment_local_music.xml +++ b/app/src/main/res/layout/fragment_local_music.xml @@ -42,12 +42,11 @@ - - - + - - + diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index 33d8dd1..c4a62e1 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -38,6 +38,7 @@ android:focusable="true" android:focusableInTouchMode="true" android:paddingStart="15dp" + android:hint="周杰伦" android:textColor="@color/white" android:textSize="16sp" /> diff --git a/app/src/main/res/layout/fragment_search_content.xml b/app/src/main/res/layout/fragment_search_content.xml index 1c8ef10..d202dd6 100644 --- a/app/src/main/res/layout/fragment_search_content.xml +++ b/app/src/main/res/layout/fragment_search_content.xml @@ -1,17 +1,59 @@ - + android:layout_height="match_parent"> - + android:layout_height="match_parent"> + + - + - \ No newline at end of file + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/recycler_song_item.xml b/app/src/main/res/layout/recycler_song_item.xml index 4f1d896..2a0968f 100644 --- a/app/src/main/res/layout/recycler_song_item.xml +++ b/app/src/main/res/layout/recycler_song_item.xml @@ -47,7 +47,7 @@ android:ellipsize="end" android:maxEms="15" android:singleLine="true" - android:textColor="@color/short_white" + android:textColor="@color/white_blue" android:textSize="14sp"/> diff --git a/app/src/main/res/mipmap-xxhdpi/icon.png b/app/src/main/res/mipmap-xxhdpi/icon.png new file mode 100644 index 0000000..eadf99e Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon.png differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index c7f53cd..be416a8 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -12,12 +12,13 @@ #80FFFFFF #80010738 - #99010738 + #80010733 #2e3259 #0f1934 #00000000 #2ad3df #161e31 + #000 #bcb9b9 #FFC66D #caeefc diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eb883d6..dccad60 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -10,7 +10,7 @@ 自建歌单 我喜欢 默认收藏 - 人生几何,对酒当歌 + 人生几何,对酒当歌 搜索 清空搜索历史 取消 diff --git a/master b/master new file mode 100644 index 0000000..e69de29