/**
* 该类用来帮助对不同的UI界面进行加载
*/
public abstract class UILoader extends FrameLayout {
private View mLoadingView;
private View mNetworkErrorView;
private View mDataEmptyView;
private View mSuccessView;
private OnRetryLoadDataListener mOnRetryLoadDataListener;
/**
* 表示不同状态的类
*/
public enum UIStatus {
LOADING, SUCCESS, NETWORK_ERROR, EMPTY, NONE
}
private UIStatus mCurrentStatus = UIStatus.NONE; // 初始为none
public UILoader(@NonNull Context context) {
// 改成this,保证入口唯一
this(context, null);
}
public UILoader(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public UILoader(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 初始化
init();
}
/**
* 更新当前的状态
*/
public void updateStatus(UIStatus status) {
mCurrentStatus = status;
// 更新UI一定要在主线程
BaseApplication.getHandler().post(new Runnable() {
@Override
public void run() {
switchUIByCurrentStatus();
}
});
}
/**
* 初始化UI
*/
private void init() {
switchUIByCurrentStatus();
}
/**
* 选择当前的UI状态
*/
private void switchUIByCurrentStatus() {
// 加载中
if (mLoadingView == null) {
mLoadingView = getLoadingView();
addView(mLoadingView);
}
// 根据状态选择可见/不可见
mLoadingView.setVisibility(mCurrentStatus == UIStatus.LOADING ? View.VISIBLE : GONE);
// 网络错误
if (mNetworkErrorView == null) {
mNetworkErrorView = getNetworkErrorView();
addView(mNetworkErrorView);
}
// 根据状态选择可见/不可见
mNetworkErrorView.setVisibility(mCurrentStatus == UIStatus.NETWORK_ERROR ? View.VISIBLE : GONE);
// 数据为空
if (mDataEmptyView == null) {
mDataEmptyView = getDataEmptyView();
addView(mDataEmptyView);
}
// 根据状态选择可见/不可见
mDataEmptyView.setVisibility(mCurrentStatus == UIStatus.EMPTY ? View.VISIBLE : GONE);
// 成功
if (mSuccessView == null) {
// 因为成功的view不知道具体情况,所以定义为抽象方法,由子类实现
mSuccessView = getSuccessView(this);
addView(mSuccessView);
}
// 根据状态选择可见/不可见
mSuccessView.setVisibility(mCurrentStatus == UIStatus.SUCCESS ? View.VISIBLE : GONE);
}
/**
* 返回空数据的界面
* @return
*/
protected View getDataEmptyView() {
return LayoutInflater.from(getContext()).inflate(R.layout.fragment_empty_view, this, false);
}
/**
* 返回网络错误的界面
* @return
*/
private View getNetworkErrorView() {
View networkErrorView = LayoutInflater.from(getContext()).inflate(R.layout.fragment_error_view, this, false);
// 网络错误时再次点击进行重新加载
// 先获取网络错误位置区域,进行监听
LinearLayout networkItem = networkErrorView.findViewById(R.id.network_error_icon);
networkItem.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
// 监听回调加载,具体实现在RecommentFragment
if (mOnRetryLoadDataListener != null) {
mOnRetryLoadDataListener.OnRetryLoadData();
}
}
});
return networkErrorView;
}
/**
* 返回成功的界面,子类实现
* @return
*/
protected abstract View getSuccessView(ViewGroup container);
/**
* 获取加载中的界面
* @return
*/
private View getLoadingView() {
return LayoutInflater.from(getContext()).inflate(R.layout.fragment_loading_view, this, false);
}
/**
* 网络不好时,点击重新加载接口
*/
public interface OnRetryLoadDataListener{
void OnRetryLoadData();
}
// 设置接口
public void setOnRetryLoadDataListener(OnRetryLoadDataListener callback) {
this.mOnRetryLoadDataListener = callback;
}
}
各种默认状态界面:
空内容
R.layout.fragment_empty_view
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="75dp"
android:layout_height="75dp"
android:src="@mipmap/content_empty" />
<TextView
android:id="@+id/empty_view_tips_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="9dp"
android:text="呜呜~没有内容.."
android:textSize="18sp" />
</LinearLayout>
</RelativeLayout>
网络状态错误:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/network_error_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="75dp"
android:layout_height="75dp"
android:src="@mipmap/network_error" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="9dp"
android:text="网络错误,请点击重试" />
</LinearLayout>
</RelativeLayout>
加载中:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical">
<com.smart.himalaya.views.LoadingView
android:layout_width="40dp"
android:layout_height="40dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="14dp"
android:text="正在玩命加载中..."/>
</LinearLayout>
</RelativeLayout>
加载成功的界面具体由子类复写实现
使用方法:
/**
* 推荐fragment
*/
public class RecommendFragment extends BaseFragment implements IRecommendViewCallback, UILoader.OnRetryLoadDataListener, AlbumListAdapter.OnAlbumItemClickListener {
private static final String TAG = "RecommendFragment";
private View mRootView;
private RecyclerView mRecommendRv;
private AlbumListAdapter mAlbumListAdapter;
private RecommendPresenter mRecommendPresenter;
private UILoader mUiLoader;
@Override
protected View onSubViewLoaded(LayoutInflater inflater, ViewGroup container) {
mUiLoader = new UILoader(getContext()) {
@Override
protected View getSuccessView(ViewGroup container) {
return onSuccessView(inflater, container);
}
};
// 逻辑层进行处理
mRecommendPresenter = RecommendPresenter.getInstance();
// 注册view到逻辑层,逻辑层便可以控制view层
mRecommendPresenter.registerViewCallback(this);
mRecommendPresenter.getRecommendList();
/**
* 先要将mUiLoader与其父类解绑,安卓中不能重复绑定
*/
if (mUiLoader.getParent() instanceof ViewGroup) {
((ViewGroup) mUiLoader.getParent()).removeView(mUiLoader);
}
// mUiLoader对UILoader进行监听
mUiLoader.setOnRetryLoadDataListener(this);
return mUiLoader;
}
/**
* 返回成功的界面
*
* @return
*/
private View onSuccessView(LayoutInflater inflater, ViewGroup container) {
mRootView = inflater.inflate(R.layout.fragment_recomment, container, false);
// recyclerView的使用
// 1.找到控件
mRecommendRv = mRootView.findViewById(R.id.recommend_list);
TwinklingRefreshLayout twinklingRefreshLayout = mRootView.findViewById(R.id.over_bound_view);
// 给recyclerView设置上拉/下拉回弹效果
twinklingRefreshLayout.setPureScrollModeOn();
// 2.设置布局管理器
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecommendRv.setLayoutManager(linearLayoutManager);
// 每个item添加分割间距
mRecommendRv.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
// UIUtil.dip2px 把dp转为像素
// 设置每个item的上下左右间距
outRect.left = UIUtil.dip2px(view.getContext(), 5);
outRect.top = UIUtil.dip2px(view.getContext(), 5);
outRect.right = UIUtil.dip2px(view.getContext(), 5);
outRect.bottom = UIUtil.dip2px(view.getContext(), 5);
}
});
// 3.设置适配器
mAlbumListAdapter = new AlbumListAdapter();
mRecommendRv.setAdapter(mAlbumListAdapter);
mAlbumListAdapter.setOnAlbumItemClickListener(this);
return mRootView;
}
@Override
public void onRecommendData(List<Album> albumList) {
// 把数据设置给适配器,并且更新
mAlbumListAdapter.setData(albumList);
mUiLoader.updateStatus(UILoader.UIStatus.SUCCESS);
}
/**
* 网络错误
*/
@Override
public void onNetworkError() {
mUiLoader.updateStatus(UILoader.UIStatus.NETWORK_ERROR);
}
/**
* 数据为空
*/
@Override
public void onDataEmpty() {
mUiLoader.updateStatus(UILoader.UIStatus.EMPTY);
}
/**
* 正在加载
*/
@Override
public void onLoading() {
mUiLoader.updateStatus(UILoader.UIStatus.LOADING);
}
@Override
public void onDestroyView() {
super.onDestroyView();
// 这里取消逻辑层对view的注册
if (mRecommendPresenter != null) {
mRecommendPresenter.unRegisterViewCallback(this);
mRecommendPresenter = null;
}
if (mAlbumListAdapter != null) {
mAlbumListAdapter.setOnAlbumItemClickListener(null);
mAlbumListAdapter = null;
}
}
// 网络不好,点击网络重新加载
@Override
public void OnRetryLoadData() {
if (mRecommendPresenter != null) {
mRecommendPresenter.getRecommendList();
}
}
/**
* 实现点击recycler的item展示详情界面
* @param position
*/
@Override
public void onItemClick(int position, Album album) {
// 将Album设置给详情页的逻辑层
AlbumDetailPresenter.getInstance().setTargetAlbum(album);
Intent intent = new Intent(getContext(), AlbumDetailActivity.class);
startActivity(intent);
}
}
/**
* 订阅fragment
*/
public class SubscriptionFragment extends BaseFragment implements ISubscriptionViewCallback, AlbumListAdapter.OnAlbumItemClickListener, AlbumListAdapter.OnAlbumItemLongClickListener, ConfirmDialog.ConfirmDialogClickListener {
private TwinklingRefreshLayout mTwinklingRefreshLayout;
private RecyclerView mSubscriptionRv;
private AlbumListAdapter mAlbumListAdapter;
private SubscriptionPresenter mSubscriptionPresenter;
private ConfirmDialog mConfirmDialog;
private Album mCurrentAlbum = null;
private UILoader mUiLoader;
private View mRootView;
@Override
protected View onSubViewLoaded(LayoutInflater inflater, ViewGroup container) {
if (mUiLoader == null) {
mUiLoader = new UILoader(getContext()) {
@Override
protected View getSuccessView(ViewGroup container) {
return createSuccessView(inflater, container);
}
@Override
protected View getDataEmptyView() {
View emptyView = LayoutInflater.from(getContext()).inflate(R.layout.fragment_empty_view, this,
false);
TextView emptyTv = emptyView.findViewById(R.id.empty_view_tips_tv);
emptyTv.setText(R.string.no_sub_content_tips_text);
return emptyView;
}
};
}
/**
* 先要将mUiLoader与其父类解绑,安卓中不能重复绑定
*/
if (mUiLoader.getParent() instanceof ViewGroup) {
((ViewGroup) mUiLoader.getParent()).removeView(mUiLoader);
}
return mUiLoader;
}
private View createSuccessView(LayoutInflater inflater, ViewGroup container) {
mRootView = inflater.inflate(R.layout.fragment_subscription, container, false);
// 1.找到控件
mTwinklingRefreshLayout = mRootView.findViewById(R.id.sub_over_scroll_view);
mSubscriptionRv = mRootView.findViewById(R.id.sub_list);
// recyclerView设置上拉/下拉回弹效果
mTwinklingRefreshLayout.setPureScrollModeOn();
// 2.设置布局管理器
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
mSubscriptionRv.setLayoutManager(linearLayoutManager);
// 每个item添加分割间距
mSubscriptionRv.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
// UIUtil.dip2px 把dp转为像素
// 设置每个item的上下左右间距
outRect.left = UIUtil.dip2px(view.getContext(), 5);
outRect.top = UIUtil.dip2px(view.getContext(), 5);
outRect.right = UIUtil.dip2px(view.getContext(), 5);
outRect.bottom = UIUtil.dip2px(view.getContext(), 5);
}
});
// 3.设置适配器
mAlbumListAdapter = new AlbumListAdapter();
mSubscriptionRv.setAdapter(mAlbumListAdapter);
mAlbumListAdapter.setOnAlbumItemClickListener(this);
mAlbumListAdapter.setOnAlbumItemLongClickListener(this);
// 逻辑层获取数据
mSubscriptionPresenter = SubscriptionPresenter.getInstance();
mSubscriptionPresenter.registerViewCallback(this);
mSubscriptionPresenter.getSubscriptionList();
if (mUiLoader != null) {
mUiLoader.updateStatus(UILoader.UIStatus.LOADING);
}
return mRootView;
}
@Override
public void onAddResult(boolean isAdd) {
}
@Override
public void onDeleteResult(boolean isDelete) {
String isCancel = BaseApplication.getAppContext().getResources().getString(isDelete ? R.string.cancel_sub_success :
R.string.cancel_sub_failed);
Toast.makeText(BaseApplication.getAppContext(), isCancel, Toast.LENGTH_SHORT).show();
}
@Override
public void onSubscriptionLoaded(List<Album> albums) {
if (albums == null || albums.size() == 0) {
if (mUiLoader != null) {
mUiLoader.updateStatus(UILoader.UIStatus.EMPTY);
}
} else {
if (mUiLoader != null) {
mUiLoader.updateStatus(UILoader.UIStatus.SUCCESS);
}
}
if (mSubscriptionPresenter != null && mAlbumListAdapter != null) {
mAlbumListAdapter.setData(albums);
}
}
@Override
public void onAddSubFull() {
// 订阅数量已经最大
Toast.makeText(BaseApplication.getAppContext(), "订阅数量已满" + Constants.MAX_SUB_COUNT, Toast.LENGTH_SHORT).show();
}
@Override
public void onDestroyView() {
super.onDestroyView();
// 这里取消逻辑层对view的注册
if (mSubscriptionPresenter != null) {
mSubscriptionPresenter.unRegisterViewCallback(this);
mSubscriptionPresenter = null;
}
if (mAlbumListAdapter != null) {
mAlbumListAdapter.setOnAlbumItemClickListener(null);
mAlbumListAdapter = null;
}
}
/**
* 实现点击recycler的item展示详情界面
*
* @param position
*/
@Override
public void onItemClick(int position, Album album) {
// 将Album设置给详情页的逻辑层
AlbumDetailPresenter.getInstance().setTargetAlbum(album);
Intent intent = new Intent(getContext(), AlbumDetailActivity.class);
startActivity(intent);
}
@Override
public void onItemLongClick(Album album) {
this.mCurrentAlbum = album;
// 长按取消订阅
if (getActivity() != null) {
/**
* 这里需要传入fragment寄生的activity,不能传入BaseContext.getApplication
* 因为dialog是在activity之上的
*/
mConfirmDialog = new ConfirmDialog(getActivity());
mConfirmDialog.setConfirmDialogClickListener(this);
mConfirmDialog.show();
}
}
@Override
public void setClickCancelSub() {
// 取消订阅
if (mCurrentAlbum != null && mSubscriptionPresenter != null) {
mSubscriptionPresenter.deleteSubscription(mCurrentAlbum);
}
}
@Override
public void setClickThinkMore() {
// 我再想想
}
}
/**
* 历史fragment
*/
public class HistoryFragment extends BaseFragment implements IHistoryViewCallback, TrackListAdapter.ItemClickListener {
private UILoader mUiLoader;
private View mRootView;
private TwinklingRefreshLayout mTwinklingRefreshLayout;
private RecyclerView mHistoryRv;
private TrackListAdapter mTrackListAdapter;
private HistoryPresenter mHistoryPresenter;
@Override
protected View onSubViewLoaded(LayoutInflater inflater, ViewGroup container) {
if (mUiLoader == null) {
mUiLoader = new UILoader(getContext()) {
@Override
protected View getSuccessView(ViewGroup container) {
return createSuccessView(inflater, container);
}
};
}
/**
* 先要将mUiLoader与其父类解绑,安卓中不能重复绑定
*/
if (mUiLoader.getParent() instanceof ViewGroup) {
((ViewGroup) mUiLoader.getParent()).removeView(mUiLoader);
}
return mUiLoader;
}
private View createSuccessView(LayoutInflater inflater, ViewGroup container) {
mRootView = inflater.inflate(R.layout.fragment_history, container, false);
// 1.找到控件
mTwinklingRefreshLayout = mRootView.findViewById(R.id.history_over_bound_view);
mHistoryRv = mRootView.findViewById(R.id.history_list);
// 设置上拉下拉回弹效果
mTwinklingRefreshLayout.setPureScrollModeOn();
// 2.设置布局管理器
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
mHistoryRv.setLayoutManager(linearLayoutManager);
mHistoryRv.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
// UIUtil.dip2px 把dp转为像素
// 设置每个item的上下左右间距
outRect.left = UIUtil.dip2px(view.getContext(), 5);
outRect.top = UIUtil.dip2px(view.getContext(), 5);
outRect.right = UIUtil.dip2px(view.getContext(), 5);
outRect.bottom = UIUtil.dip2px(view.getContext(), 5);
}
});
// 3.设置适配器
mTrackListAdapter = new TrackListAdapter();
mTrackListAdapter.setItemClickListener(this);
mHistoryRv.setAdapter(mTrackListAdapter);
// 4.逻辑层获取数据
mHistoryPresenter = HistoryPresenter.getInstance();
mHistoryPresenter.registerViewCallback(this);
mHistoryPresenter.loadHistoryList();
if (mUiLoader != null) {
mUiLoader.updateStatus(UILoader.UIStatus.LOADING);
}
return mRootView;
}
@Override
public void onHistoriesLoad(List<Track> tracks) {
if (tracks == null || tracks.size() == 0) {
if (mUiLoader != null) {
mUiLoader.updateStatus(UILoader.UIStatus.EMPTY);
}
} else {
if (mUiLoader != null) {
mUiLoader.updateStatus(UILoader.UIStatus.SUCCESS);
}
}
if (mHistoryPresenter != null && mTrackListAdapter != null) {
mTrackListAdapter.setData(tracks);
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
// 这里取消逻辑层对view的注册
if (mHistoryPresenter != null) {
mHistoryPresenter.unRegisterViewCallback(this);
mHistoryPresenter = null;
}
}
@Override
public void onItemClick(List<Track> tracks, int playIndex) {
// 跳转播放
PlayerPresenter playerPresenter = PlayerPresenter.getInstance();
playerPresenter.setPlayList(tracks, playIndex);
// 跳转播放的界面
Intent intent = new Intent(getActivity(), PlayerActivity.class);
startActivity(intent);
}
}
BaseFragment
public abstract class BaseFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return onSubViewLoaded(inflater, container);
}
protected abstract View onSubViewLoaded(LayoutInflater layoutInflater, ViewGroup container);
@Override
public void onResume() {
super.onResume();
onRefresh();
}
protected void onRefresh() {
}
}
BaseApplication
public class BaseApplication extends Application {
private static Handler sHandler = null;
@SuppressLint("StaticFieldLeak")
private static Context sContext = null;
@Override
public void onCreate() {
super.onCreate();
CommonRequest mXimalaya = CommonRequest.getInstanse();
if (DTransferConstants.isRelease) {
String mAppSecret = "8646d66d6abe2efd14f2891f9fd1c8af";
mXimalaya.setAppkey("9f9ef8f10bebeaa83e71e62f935bede8");
mXimalaya.setPackid("com.app.test.android");
mXimalaya.init(this, mAppSecret);
} else {
String mAppSecret = "0a09d7093bff3d4947a5c4da0125972e";
mXimalaya.setAppkey("f4d8f65918d9878e1702d49a8cdf0183");
mXimalaya.setPackid("com.ximalaya.qunfeng");
mXimalaya.init(this, mAppSecret);
}
//初始化播放器
XmPlayerManager.getInstance(this).init();
//初始化LogUtil
LogUtil.init(this.getPackageName(), false);
sHandler = new Handler();
sContext = getApplicationContext();
}
public static Context getAppContext() {
return sContext;
}
public static Handler getHandler() {
return sHandler;
}
}