前段時間一直在忙找工作的事,好久沒有寫博客了,最近在學(xué)習(xí)一個實戰(zhàn)項目http://coding.imooc.com/class/evaluation/100.html,講到了基類的封裝,故在此記錄一下。主要涉及到Activity,Fragment和RecyclerView的適配器的封裝。
一、Activity基類的封裝
由于都有詳細的注釋,并且代碼簡單,就不再解釋了,文中使用了ButterKnife。
public abstract class Activity extends AppCompatActivity {
protected Unbinder mUnbinder;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//在界面初始化之前初始化窗口
initWindows();
if (initArgs(getIntent().getExtras())) {
int layoutId = getContentLayoutId();
setContentView(layoutId);
initWidget();
initData();
} else {
finish();
}
}
/**
* 初始化窗口
*/
protected void initWindows(){
}
/**
* 初始化參數(shù)
* @param bundle 需要初始化的參數(shù)
* @return 如果參數(shù)正確返回true,錯誤返回false
*/
protected boolean initArgs(Bundle bundle) {
return true;
}
/**
* 獲得當前界面的資源文件Id
* @return 界面的資源文件Id
*/
protected abstract int getContentLayoutId();
/**
* 初始化控件
*/
protected void initWidget() {
mUnbinder = ButterKnife.bind(this);
}
/**
* 初始化數(shù)據(jù)
*/
protected void initData() {
}
@Override
public boolean onSupportNavigateUp() {
//當點擊界面導(dǎo)航返回時,finish當前界面
finish();
return super.onSupportNavigateUp();
}
@Override
public void onBackPressed() {
//獲得當前Activity的所有Fragment
@SuppressWarnings("RestrictedApi")
List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
if (fragmentList != null && fragmentList.size() > 0){
for (Fragment fragment : fragmentList) {
//是否是我們自定義的Fragment
if (fragment instanceof cn.codekong.common.app.Fragment){
if (((cn.codekong.common.app.Fragment)fragment).onBackPressed()){
//Fragment處理了返回事件
return;
}
}
}
}
super.onBackPressed();
finish();
}
}
二、Fragment基類的封裝
public abstract class Fragment extends android.support.v4.app.Fragment {
protected View mRoot;
protected Unbinder mRootUnbinder;
@Override
public void onAttach(Context context) {
super.onAttach(context);
initArgs(getArguments());
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if (mRoot == null){
int layoutId = getContentLayoutId();
//初始化當前的根布局,但是不在創(chuàng)建時就添加到container里面
View root = inflater.inflate(layoutId, container, false);
initWidget(root);
mRoot = root;
}else {
if (mRoot.getParent() != null){
//把當前的根布局從其父控件中移除
((ViewGroup)mRoot.getParent()).removeView(mRoot);
}
}
return mRoot;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//當View創(chuàng)建完成后初始化數(shù)據(jù)
initData();
}
/**
* 初始化參數(shù)
* @param bundle 需要初始化的參數(shù)
*/
protected void initArgs(Bundle bundle) {
}
/**
* 獲得當前界面的資源文件Id
*
* @return 資源文件Id
*/
protected abstract int getContentLayoutId();
/**
* 初始化控件
*/
protected void initWidget(View root) {
mRootUnbinder = ButterKnife.bind(this, root);
}
/**
* 初始化數(shù)據(jù)
*/
protected void initData() {
}
/**
* 返回按鍵觸發(fā)時調(diào)用
* @return 返回true代表自己處理返回邏輯,Activity不用處理
* 返回false代表沒有處理邏輯,交由Activity處理
*/
public boolean onBackPressed(){
return false;
}
}
三、RecyclerView適配器基類的封裝
public abstract class RecyclerAdapter<Data> extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder<Data>>
implements View.OnClickListener, View.OnLongClickListener, AdapetrCallback<Data> {
private final List<Data> mDataList;
private AdapterListener<Data> mAdapterListener;
/**
* 構(gòu)造函數(shù)
*/
public RecyclerAdapter() {
this(null);
}
public RecyclerAdapter(AdapterListener<Data> listener) {
this(new ArrayList<Data>(), listener);
}
public RecyclerAdapter(List<Data> dataList, AdapterListener<Data> listener) {
this.mDataList = dataList;
this.mAdapterListener = listener;
}
/**
* 創(chuàng)建一個ViewHolder
*
* @param parent RecyclerView
* @param viewType 界面的類型,約定為xml布局的Id
* @return
*/
@Override
public ViewHolder<Data> onCreateViewHolder(ViewGroup parent, int viewType) {
//將xml布局初始化為View
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View root = inflater.inflate(viewType, parent, false);
ViewHolder<Data> holder = onCreateViewHolder(root, viewType);
//設(shè)置View的Tag將View和Holder進行關(guān)聯(lián)
root.setTag(R.id.tag_recycler_holder, holder);
//設(shè)置事件點擊
root.setOnClickListener(this);
root.setOnLongClickListener(this);
//進行界面注解綁定
holder.mUnbinder = ButterKnife.bind(holder, root);
//綁定callback
holder.mCallback = this;
return holder;
}
/**
* 獲得一個新的ViewHolder
*
* @param root 根布局
* @param viewType 布局類型,其實就是xml的Id
* @return ViewHolder
*/
protected abstract ViewHolder<Data> onCreateViewHolder(View root, int viewType);
/**
* 復(fù)寫默認的布局類型返回
*
* @param position 坐標
* @return 重寫后返回的是xml文件的Id
*/
@Override
public int getItemViewType(int position) {
return getItemViewType(position, mDataList.get(position));
}
/**
* 得到布局的類型
*
* @param position 坐標
* @param data 當前的數(shù)據(jù)
* @return xml文件的Id, 用于創(chuàng)建ViewHolder
*/
@LayoutRes
protected abstract int getItemViewType(int position, Data data);
/**
* 綁定數(shù)據(jù)到Holder上
*
* @param holder ViewHolder
* @param position 坐標
*/
@Override
public void onBindViewHolder(ViewHolder<Data> holder, int position) {
//獲得需要綁定的數(shù)據(jù)
Data data = mDataList.get(position);
//觸發(fā)綁定方法
holder.bind(data);
}
/**
* 得到當前集合的數(shù)據(jù)量
*
* @return
*/
@Override
public int getItemCount() {
return mDataList.size();
}
/**
* 插入一條數(shù)據(jù)并通知插入更新
*
* @param data
*/
public void add(Data data) {
mDataList.add(data);
notifyItemInserted(mDataList.size() - 1);
}
/**
* 插入多條數(shù)據(jù),并通知這一段集合更新
*
* @param dataList
*/
public void add(Data... dataList) {
if (dataList != null && dataList.length > 0) {
int startPos = mDataList.size();
Collections.addAll(mDataList, dataList);
notifyItemRangeInserted(startPos, dataList.length);
}
}
/**
* 插入多條數(shù)據(jù),并通知這一段集合更新
*
* @param dataList
*/
public void add(Collection<Data> dataList) {
if (dataList != null && dataList.size() > 0) {
int startPos = mDataList.size();
mDataList.addAll(dataList);
notifyItemRangeInserted(startPos, dataList.size());
}
}
/**
* 刪除操作
*/
public void clear() {
mDataList.clear();
notifyDataSetChanged();
}
/**
* 替換為一個新的集合,其中包括清空
*
* @param dataList
*/
public void replace(Collection<Data> dataList) {
mDataList.clear();
if (dataList == null || dataList.size() == 0) {
return;
}
mDataList.addAll(dataList);
notifyDataSetChanged();
}
@Override
public void onClick(View v) {
ViewHolder viewHolder = (ViewHolder) v.getTag(R.id.tag_recycler_holder);
if (mAdapterListener != null) {
//得到ViewHolder當前對應(yīng)的適配器中的坐標
int pos = viewHolder.getAdapterPosition();
//回調(diào)方法
mAdapterListener.onItemClick(viewHolder, mDataList.get(pos));
}
}
@Override
public boolean onLongClick(View v) {
ViewHolder viewHolder = (ViewHolder) v.getTag(R.id.tag_recycler_holder);
if (mAdapterListener != null) {
//得到ViewHolder當前對應(yīng)的適配器中的坐標
int pos = viewHolder.getAdapterPosition();
//回調(diào)方法
mAdapterListener.onItemLongClick(viewHolder, mDataList.get(pos));
return true;
}
return false;
}
/**
* 設(shè)置監(jiān)聽器
*
* @param adapterListener
*/
public void setAdapterListener(AdapterListener<Data> adapterListener) {
this.mAdapterListener = adapterListener;
}
/**
* 自定義監(jiān)聽器
*
* @param <Data> 泛型
*/
public interface AdapterListener<Data> {
//當Item點擊時出發(fā)
void onItemClick(RecyclerAdapter.ViewHolder holder, Data data);
//當Item長按時觸發(fā)
void onItemLongClick(RecyclerAdapter.ViewHolder holder, Data data);
}
/**
* 自定義的ViewHolder
*
* @param <Data> 泛型類型
*/
public static abstract class ViewHolder<Data> extends RecyclerView.ViewHolder {
protected Data mData;
private Unbinder mUnbinder;
private AdapetrCallback<Data> mCallback;
public ViewHolder(View itemView) {
super(itemView);
}
/**
* 用于綁定數(shù)據(jù)
*
* @param data 需要綁定的數(shù)據(jù)
*/
void bind(Data data) {
this.mData = data;
onBind(data);
}
/**
* 當數(shù)據(jù)綁定時進行回調(diào),必須復(fù)寫
*
* @param data 需要綁定的數(shù)據(jù)
*/
protected abstract void onBind(Data data);
/**
* holder自己對自己的Data進行更新
*
* @param data 需要更新的數(shù)據(jù)
*/
public void updateData(Data data) {
if (mCallback != null) {
mCallback.update(data, this);
}
}
}
}
public interface AdapetrCallback<Data> {
void update(Data data, RecyclerAdapter.ViewHolder<Data> holder);
}
四、后記
基類的封裝可以有效地提高代碼的復(fù)用性,減少代碼了,希望上面的分享可以幫助到需要的人。