终于到了BaseActivity的封装了,在本章中将对通用性的一些方法和操作进行抽取,放到Base中。
先起个名字,我们的Base就叫CandyBaseActivity吧,Candy是糖果的意思,我希望这一套东西能让人像吃糖果一样的甜!
在本篇中关于Base,我们需要进行两种封装:
- CandyBaseActivity,最基本,最底层的Base,附带通用操作的封装。
- CandyLoadingBaseActivity继承至CandyBaseActivity,不是所有的页面都是需要弹窗的,像弹窗需要重写很多的方法,就不适合放到最底层。
- MVPBaseActivity,进行MVP分层的Base,里面包含生命周期的订阅和取消订阅。
首先确定我们现阶段能封装什么:
每次要引用上下文都用类名的方式来指定,这就比较繁琐了。
protected Activity mActivity;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = this;
}
直接通过工具类T来调用showToast方法在原来的基础上市比较方便,但是一直需要传递一个 context
就比较让人烦躁了,所以将showToast放到Base中。代码如下:
/**
* 显示文本信息
*
* @param text 文本信息
*/
public void showToast(String text) {
T.showToast(mActivity, text);
}
/**
* 显示文本信息
*
* @param resId 文本资源id信息
*/
public void showToast(int resId) {
T.showToast(mActivity, resId);
}
showToast方法定义为public,是为了能在其他地方,如:Presenter中进行 强转
后直接调用。
关于Activity的切换动画有各种各样的,根据不同的喜好有不同的做法,我这里使用的是:右滑进入、左滑退出
,其他动画自行探索。
setup_next_in.xml
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="100%p"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="0" >
translate>
setup_next_out.xml
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="-100%p"
android:toYDelta="0" />
setup_pre_in.xml
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="-100%p"
android:fromYDelta="0"
android:toYDelta="0"
android:toXDelta="0"/>
setup_pre_out.xml
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100%p"
android:toYDelta="0" />
/**
* Activity的跳转动画
*
* @author aohanyao create in 2018年10月04日02:36:34
*/
public class ActivityAnimUtils {
/**
* 跳转到
*
* @param activity
*/
public static void to(Activity activity) {
activity.overridePendingTransition(R.anim.setup_next_in,
R.anim.setup_next_out);
}
/**
* 退出动画
*/
public static void out(Activity activity) {
activity.overridePendingTransition(R.anim.setup_pre_in, R.anim.setup_pre_out);
}
}
/**
* 右边划出
*/
protected void slideLeftOut() {
ActivityAnimUtils.out(mActivity);
}
/**
* 进入
*/
protected void slideRightIn() {
ActivityAnimUtils.to(mActivity);
}
在startActivity之后调用 slideRightIn()
,finish()
的时候调用 slideLeftOut()
原本常用的方法是:startActivity(new Intent(mActivity, Target.class));
,这其中 new Intent()这一部分都是冗余的,我们可以封装一下,其中关于值的传递采用的是一个Pair
的可变参数,然后根据不同的类型,将数据填充到intent中。具体代码如下:
/**
* 打开 Activity
*
* @param activity
*/
protected void launchActivity(Class<? extends Activity> activity) {
startActivity(new Intent(mActivity, activity));
// 加上动画
slideRightIn();
}
/**
* 打开 Activity
*
* @param activity
*/
protected void launchActivityForResult(Class<? extends Activity> activity, int requestCode) {
startActivityForResult(new Intent(mActivity, activity), requestCode);
// 加上动画
slideRightIn();
}
/**
* 打开新的 Activity
*
* @param activity 目标Activity
* @param pairs 键值对
*/
protected void launchActivity(Class<? extends Activity> activity, Pair<String, Object>... pairs) {
Intent intent = new Intent(mActivity, activity);
// 填充数据
IntentUtils.fillIntent(intent, pairs);
startActivity(intent);
// 加上动画
slideRightIn();
}
/**
* 打开新的 Activity
*
* @param activity 目标Activity
* @param pairs 键值对
*/
protected void launchActivityForResult(Class<? extends Activity> activity, int requestCode, Pair<String, Object>... pairs) {
Intent intent = new Intent(mActivity, activity);
// 填充数据
IntentUtils.fillIntent(intent, pairs);
startActivityForResult(intent, requestCode);
// 加上动画
slideRightIn();
}
关于 fillIntent
,这个方法主要是判断参数中值的类类型,然后进行intent的填充:
/**
* Intent工具类
*/
public class IntentUtils {
/**
* 填充intent数据,暂时只写了常用的一些数据格式,不常用的没写
*
* @param intent
* @param pairs
*/
public static void fillIntent(Intent intent, Pair<String, Object>[] pairs) {
if (pairs != null) {
for (Pair<String, Object> pair : pairs) {
Object value = pair.second;
//判断不同的类型,进行强转和存放
if (value instanceof Boolean) {
intent.putExtra(pair.first, (Boolean) value);
}
if (value instanceof Byte) {
intent.putExtra(pair.first, (Byte) value);
}
if (value instanceof Short) {
intent.putExtra(pair.first, (Short) value);
}
if (value instanceof Long) {
intent.putExtra(pair.first, (Long) value);
}
if (value instanceof Float) {
intent.putExtra(pair.first, (Float) value);
}
if (value instanceof Double) {
intent.putExtra(pair.first, (Double) value);
}
if (value instanceof Integer) {
intent.putExtra(pair.first, (Integer) value);
}
if (value instanceof String) {
intent.putExtra(pair.first, (String) value);
}
if (value instanceof Parcelable) {
intent.putExtra(pair.first, (Parcelable) value);
}
if (value instanceof Serializable) {
intent.putExtra(pair.first, (Serializable) value);
}
}
}
}
}
综上,还把前面的动画用上了。
如何调用:
//普通
launchActivity(DialogExampleActivity.class);
//普通携带参数
launchActivity(ToastExampleActivityActivity.class,
new Pair<String, Object>("key1", "value1"),
new Pair<String, Object>("key1", "value1"));
//返回值
launchActivityForResult(LoginActivity.class,200);
// 返回值携带参数
launchActivityForResult(LoginActivity.class,
200,
new Pair<String, Object>("key1", "value1"),
new Pair<String, Object>("key1", "value1"));
关于Toolbar这里使用的是 android.support.v7.widget.Toolbar
,简单又方便,先看看我们在创建的时候系统生成的Toolbar:
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
android.support.design.widget.AppBarLayout>
为了以后的扩展性和能够统一的在Base中操作,要做一下操作:
- 为AppBarLayout和Toolbar定义id资源,通过统一id来管理
- 为AppBarLayout和Toolbar定义style,将id加入到style中,在xml中直接引用style
<resources>
<item name="base_toolbar" type="id" />
<item name="base_appbar" type="id" />
resources>
<resources>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />