这两天开始放寒假,在家呆着也是呆着,遂决定找星空以前Android方向大佬写的项目学习下,看看别人代码的结构以及有什么方法可以降低代码的耦合度,然后在师兄的项目里接触到了BaseActivity,在这里记录一下
为什么设计基类
- 方便代码编写,减少重复代码和冗余逻辑,优化代码
- 优化程序架构,降低耦合度,方便拓展、修改
- 版面更干净,减少了诸如生命周期日志等重复逻辑的占用版面
设计的基本思路
- 生命周期的调试日志输出
- 绑定视图
- 常用OnClick方法
- Back方法,Toast以及Activity等操作
- 常用第三方工具(ButterKnife等)
- 标题栏是否显示,是否全屏,初始化数据等
具体基类的封装
BaseActivity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
| public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements BaseView<P> {
@BindView(R.id.toolbar) Toolbar mToolbar;
Unbinder bind;
protected ProgressDialog mProgressDialog;
protected P mPresenter;
@Override protected final void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); setContentView(bindLayout()); bind = ButterKnife.bind(this);
mPresenter = createPresenter(); if (mPresenter != null) { mPresenter.onStart(); }
prepareData(); initToolbar(); initView(); initData(savedInstanceState); initEvent(); }
protected abstract P createPresenter();
@Override public void setPresenter(P presenter) { mPresenter = presenter; }
private void initToolbar() { setSupportActionBar(mToolbar); }
protected void setToolbarTitle(String title) { if (getSupportActionBar() != null) { getSupportActionBar().setTitle(title); } }
protected void setToolbarBackEnable(String title) { if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_arrow_white_24dp); setToolbarTitle(title); }
}
protected abstract int bindLayout();
protected abstract void prepareData();
protected abstract void initView();
protected abstract void initData(Bundle savedInstanceState);
protected abstract void initEvent();
@Override public void showToast(CharSequence msg) { ToastUtils.shortToast(this, msg); }
@Override public void showToast(int msgId) { ToastUtils.shortToast(this, msgId); }
@Override public void showLoadingDialog(CharSequence msg) { if (mProgressDialog == null) { mProgressDialog = new ProgressDialog(this); mProgressDialog.setTitle(R.string.title_dialog_tips); mProgressDialog.setMessage(msg); } else { mProgressDialog.setTitle(R.string.title_dialog_tips); } mProgressDialog.show(); }
@Override public void hideLoadingDialog() { if (mProgressDialog != null && mProgressDialog.isShowing()) { mProgressDialog.dismiss(); } }
@Override protected void onDestroy() { bind.unbind(); if (mPresenter != null) { mPresenter.onDestroy(); } super.onDestroy(); }
public void hideKeyboard() { View view = getCurrentFocus(); if (view != null) { ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)). hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } }
@Override protected void onPause() { super.onPause(); MobclickAgent.onPageEnd(this.getClass().getSimpleName()); MobclickAgent.onPause(this); }
@Override protected void onResume() { super.onResume(); MobclickAgent.onPageStart(this.getClass().getSimpleName()); MobclickAgent.onResume(this); }
@Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); } return super.onOptionsItemSelected(item); } }
|
BaseFragment
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
| public abstract class BaseFragment<P extends BasePresenter> extends Fragment implements BaseView<P> {
@BindView(R.id.toolbar) Toolbar mToolbar;
private Unbinder mUnbinder; protected P mPresenter;
protected ProgressDialog mProgressDialog;
private ActionBar mActionbar;
@Nullable @Override public final View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { mPresenter = createPresenter(); if (mPresenter != null) { mPresenter.onStart(); } View root = inflater.inflate(bindLayout(), container, false); mUnbinder = ButterKnife.bind(this, root); prepareData(savedInstanceState); initToolbar(); initView(root); initData(savedInstanceState); initEvent(); return root; }
protected abstract P createPresenter();
@Override public void setPresenter(P presenter) { mPresenter = presenter; }
protected abstract void prepareData(Bundle savedInstanceState);
protected abstract int bindLayout();
protected abstract void initData(Bundle savedInstanceState);
protected abstract void initView(View rootView);
protected abstract void initEvent();
private void initToolbar() { ((AppCompatActivity) getActivity()).setSupportActionBar(mToolbar); mActionbar = ((AppCompatActivity) getActivity()).getSupportActionBar(); }
protected void setToolbarTitle(String title) { if (mActionbar != null) { mActionbar.setTitle(title); } }
protected void setToolbarBackEnable(String title) { if (mActionbar != null) { mActionbar.setDisplayHomeAsUpEnabled(true); mActionbar.setHomeAsUpIndicator(R.drawable.ic_arrow_white_24dp); } }
@Override public void showToast(CharSequence msg) { ToastUtils.shortToast(APP.getAppContext(), msg); }
@Override public void showToast(int msgId) { ToastUtils.shortToast(APP.getAppContext(), msgId); }
@Override public void onDestroy() { super.onDestroy(); }
@Override public void showLoadingDialog(CharSequence msg) { if (mProgressDialog == null) { mProgressDialog = new ProgressDialog(getContext()); mProgressDialog.setMessage(msg); } else { mProgressDialog.setTitle(R.string.title_dialog_tips); } mProgressDialog.show(); }
@Override public void hideLoadingDialog() { if (mProgressDialog != null && mProgressDialog.isShowing()) { mProgressDialog.dismiss(); } }
@Override public void onDetach() { mUnbinder.unbind(); super.onDetach(); }
@Override public void onDestroyView() { if (mPresenter != null) { mPresenter.onDestroy(); } super.onDestroyView(); }
@Override public void onResume() { super.onResume(); MobclickAgent.onPageStart(this.getClass().getSimpleName()); }
@Override public void onPause() { super.onPause(); MobclickAgent.onPageEnd(this.getClass().getSimpleName()); }
}
|
BasePresenter
1 2 3 4 5 6 7
| public interface BasePresenter {
void onStart();
void onDestroy();
}
|
BaseView
1 2 3 4 5 6 7 8 9 10 11 12 13
| public interface BaseView<P> {
void setPresenter(P presenter);
void showToast(CharSequence msg);
void showToast(int msgId);
void showLoadingDialog(CharSequence msg);
void hideLoadingDialog();
}
|
Impl类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public abstract class BasePresenterImpl implements BasePresenter { protected CompositeDisposable mSubscriptions;
@Override public void onStart() { if (mSubscriptions == null) { mSubscriptions = new CompositeDisposable(); } }
@Override public void onDestroy() { if (mSubscriptions != null) { mSubscriptions.dispose(); mSubscriptions.clear(); } } }
|
APP类
用于获取全局的context
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class APP extends Application {
private static Context appContext; private static long exitTime = 0;
public static Context getAppContext() { return appContext; }
@Override public void onCreate() { super.onCreate(); appContext = getApplicationContext(); }
public static void exitApp() { if (System.currentTimeMillis() - exitTime > 2000) { ToastUtils.shortToast(getAppContext(), appContext.getString(R.string.text_press_again)); exitTime = System.currentTimeMillis(); } else { android.os.Process.killProcess(android.os.Process.myPid()); } } }
|
具体使用
Contract 契约类
契约类用于定义同一个界面的view和presenter的接口,通过规范的方法命名或注释,可以清晰的看到整个页面的逻辑。
1 2 3 4 5 6 7 8 9
| public interface myContract {
interface View extends BaseView<Presenter> { }
interface Presenter extends BasePresenter {
} }
|
Presenter
1 2 3 4 5 6 7 8
| public class SamplePresenter extends BasePresenterImpl implements myContract.Presenter {
private final myContract.View mView; public SamplePresenter(myContract.View view) { mView = view; this.mView.setPresenter(this); } }
|
Activiy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class SampleActivity extends BaseActivity<myContract.Presenter> implements myContract.View {
@BindView(R.id.tv_sample_text) TextView mTvSample;
@Override protected myContract.Presenter createPresenter() { return new SamplePresenter(this); }
@Override protected int bindLayout() { return R.layout.activity_sample; }
@Override protected void prepareData() { }
@Override protected void initView() { mTvSample.setText("这是一个sample"); }
@Override protected void initData(Bundle savedInstanceState) { }
@Override protected void initEvent() { } }
|