美文网首页对移动开发有帮助Android使用场景
浅谈BaseActivity写法,促使我们更高效开发

浅谈BaseActivity写法,促使我们更高效开发

作者: 打酱油的日光灯 | 来源:发表于2018-12-26 18:56 被阅读258次

    抓住人生中的一分一秒,胜过虚度中的一月一年!

    前言

    在Android开发中,activity再常用不过了,为了高效开发,我们会将一些常用的功能和页面统一实现的效果放在基类,这样就不用写每个页面时再重新实现这些功能,下面是我总结了些内容与大家共享一下,有不足的地方希望大家提出我将进行再次完善。

    实现目标

    1、屏幕横竖屏切换,AndroidManifest中将不用再写android:screenOrientation="portrait"
    2、ButterKnife绑定页面
    3、沉浸式实现
    4、携带数据的页面跳转
    5、应用被强杀检测
    6、标题栏统一实现
    7、仿IOS侧滑finish页面实现
    8、Loading页面统一实现(可替换成骨架图)
    9、点击Edittext弹出软键盘,点击空白区域让软键盘消失
    10、结合MVP模式下的BaseActivity


    1、屏幕横竖屏切换,AndroidManifest中将不用再写android:screenOrientation="portrait"

    我们经常开发的app,一般情况下都是手机上的应用,我想大家已经设置了强制竖屏,因为横屏没有特殊要求没有必要去设置,设置了反而会出现更多问题,其次说一下8.0更新问题,页面同时设置了android:screenOrientation="portrait"和透明属性,8.0运行会出现Only fullscreen opaque activities can request orientation异常,大概意思为“只有不透明的全屏activity可以自主设置界面方向”,我们或许会引用一些第三方SDK到项目中,也许第三方会用到透明属性,我们可能在AndroidManifest中会申明android:screenOrientation="portrait"后导致莫名其妙的奔溃(小概率事件,但不排除),所以建议在BaseActivity设置比较优(当你做侧滑返回以后就不会觉得我说这么啰嗦了)

     /**
         * 设置屏幕横竖屏切换
         *
         * @param screenRoate true  竖屏     false  横屏
         */
        private void setScreenRoate(Boolean screenRoate) {
            if (screenRoate) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//设置竖屏模式
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
        }
    
     @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setScreenRoate(true);
        }
    
    2、ButterKnife绑定页面

    ButterKnife这个快速申明控件省了我们多少findViewById的时间,推荐使用,详细写一写可能有人没用过此控件
    1、依赖

    compile 'com.jakewharton:butterknife:8.8.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
    

    2、onCreate绑定页面 onDestroy取消绑定

      @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ButterKnife.bind(this);
        }
      @Override
        protected void onDestroy() {
            super.onDestroy();
            ButterKnife.bind(this).unbind();
        }
    
    3、沉浸式实现

    为了让用户感受更好的体验效果,所以我们会选择设置沉浸式,每个页面大多数都会设置一种效果,所以直接在BaseActivity设置即可

     /**
         * 沉浸式实现
         */
        protected void setStatusBar() {
            StatusBarUtil.setColor(this, getResources().getColor(R.color.colorWhite), 0);
    //        StatusBarUtil.setTranslucentForImageViewInFragment(this, 0, null);
        }
       @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setStatusBar();
        }
    

    问:如果有页面不想设置此效果
    答:在对应Activity重写setStatusBar(),做自定义操作

    4、携带数据的页面跳转

    跳转页面 startActivity(new Intent(this, MainActivity.class));不改装这已经是最简洁了,你要记住,程序员是比较懒的,能少写就少写

     /**
         * [页面跳转]
         *
         * @param clz
         */
        public void startActivity(Class<?> clz) {
            startActivity(clz, null);
        }
        /**
         * [携带数据的页面跳转]
         *
         * @param clz
         * @param bundle
         */
        public void startActivity(Class<?> clz, Bundle bundle) {
            Intent intent = new Intent();
            intent.setClass(this, clz);
            if (bundle != null) {
                intent.putExtras(bundle);
            }
            startActivity(intent);
        }
    
        /**
         * [含有Bundle通过Class打开编辑界面]
         *
         * @param cls
         * @param bundle
         * @param requestCode
         */
        public void startActivityForResult(Class<?> cls, Bundle bundle, int requestCode) {
            Intent intent = new Intent();
            intent.setClass(this, cls);
            if (bundle != null) {
                intent.putExtras(bundle);
            }
            startActivityForResult(intent, requestCode);
        }
    

    跳转页面startActivity(MainActivity.class);嗯。。。少写了几个字母

    5、应用被强杀检测

    手机开了N多个应用,可能导致内存不足,所以GC就出来工作了,也许你的App就是被杀的对象(保活处理移步其他文章),我们需要检测到APP是否被杀
    思路:
    (1)APP被杀,可以跳转到闪屏页,再跳转到MainActivity,但可能MainActivity还存在,我想让MainActivity彻底消失,所以我的思路是跳转到MainActivity,将MainActivity finish再跳转到闪屏页,再往其他页面跳转
    (2)那怎么样检测APP是否被杀呢,我进入到APP后将一个参数设置个值,如果APP被杀,也就是说我们当时设置的值已经不存在了,当我们检测到这个值和我们当时设置的值不匹配说明APP被杀了
    1、新建个常量类AppStatusConstant

    /**
     * File descripition:   APP状态跟踪器常量码
     *
     * @author lp
     * @date 2018/9/29
     */
    
    public class AppStatusConstant {
        public static final int STATUS_FORCE_KILLED=-1; //应用放在后台被强杀了
        public static final int STATUS_NORMAL=2;  //APP正常态
        //intent到MainActivity 区分跳转目的
        public static final String KEY_HOME_ACTION="key_home_action";//返回到主页面
        public static final int ACTION_BACK_TO_HOME=6; //默认值
        public static final int ACTION_RESTART_APP=9;//被强杀
    }
    

    2、新建个单例模式,用来保存值

    /**
     * File descripition:
     *
     * @author lp
     * @date 2018/9/29
     */
    
    public class AppStatusManager {
        public int appStatus= AppStatusConstant.STATUS_FORCE_KILLED;        //APP状态 初始值为没启动 不在前台状态
    
        public static AppStatusManager appStatusManager;
    
        private AppStatusManager() {
    
        }
    
        public static AppStatusManager getInstance() {
            if (appStatusManager == null) {
                appStatusManager = new AppStatusManager();
            }
            return appStatusManager;
        }
    
        public int getAppStatus() {
            return appStatus;
        }
    
        public void setAppStatus(int appStatus) {
            this.appStatus = appStatus;
        }
    }
    

    3、进入到闪屏页我便给appStatus赋值

    /**
     * File descripition:   闪屏页
     *
     * @author lp
     * @date 2018/10/16
     */
    
    public class SplashActivity extends AppCompatActivity {
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            AppStatusManager.getInstance().setAppStatus(AppStatusConstant.STATUS_NORMAL); //进入应用初始化设置成未登录状态
            super.onCreate(savedInstanceState);
        }
    }
    

    4、在BaseActivity的onCreate中去检测这个值是否是我们设置过的值

     private void initAppStatus() {
            switch (AppStatusManager.getInstance().getAppStatus()) {
                /**
                 * 应用被强杀
                 */
                case AppStatusConstant.STATUS_FORCE_KILLED:
                    //跳到主页,主页lauchmode SINGLETASK
                    protectApp();
                    break;
            }
        }
     protected void protectApp() {
            Intent intent = new Intent(this, MainActivity.class);
            intent.putExtra(AppStatusConstant.KEY_HOME_ACTION, AppStatusConstant.ACTION_RESTART_APP);
            startActivity(intent);
        }
      @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            initAppStatus();
        }
    

    5、MainActivity中接收传过来的信息,然后调整到闪屏页

      @Override
        protected void onNewIntent(Intent intent) {
            super.onNewIntent(intent);
            int action = intent.getIntExtra(AppStatusConstant.KEY_HOME_ACTION, AppStatusConstant.ACTION_BACK_TO_HOME);
            switch (action) {
                case AppStatusConstant.ACTION_RESTART_APP:
                    protectApp();
                    break;
            }
        }
     @Override
        protected void protectApp() {
            Toast.makeText(getApplicationContext(), "应用被回收重新启动", Toast.LENGTH_LONG).show();
            startActivity(new Intent(this, SplashActivity.class));
            finish();
        }
    
    6、标题栏统一实现

    每个页面大多数都会有个标题栏,实现方式我们都会,下面我介绍另一种方式,我把标题栏写到BaseActivity布局中,这样在对应的Activity就不用一遍一遍的写了,但是弊端是多了一层嵌套
    思路:我们在BaseActivity申明一个布局,其子Activity的xml塞入到父布局的一个控件中,这样就每个子Activity都会有统一的控件了(标题栏)
    1、首先新建个关于title的xml,app_title.xml(供参考)

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/rlt_base"
        android:layout_width="match_parent"
        android:layout_height="44dp"
        android:background="@color/colorWhite">
        <LinearLayout
            android:id="@+id/back"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:paddingLeft="@dimen/padding_12"
            android:paddingRight="@dimen/padding_12">
            <TextView
                android:id="@+id/back_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="@dimen/margin_8"
                android:drawableLeft="@mipmap/zuojiantou"
                android:drawablePadding="@dimen/padding_8"
                android:gravity="center"
                android:textColor="@color/colorBlack"
                android:visibility="visible" />
        </LinearLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerHorizontal="true"
            android:layout_marginLeft="80dp"
            android:layout_marginRight="80dp">
            <TextView
                android:id="@+id/tv_title"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_centerHorizontal="true"
                android:layout_centerInParent="true"
                android:ellipsize="end"
                android:gravity="center"
                android:lines="1"
                android:textColor="@color/colorBlack"
                android:textSize="@dimen/text_18" />
        </RelativeLayout>
        <TextView
            android:id="@+id/tv_right"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:drawablePadding="@dimen/padding_6"
            android:ellipsize="end"
            android:gravity="center"
            android:lines="1"
            android:paddingLeft="14dp"
            android:paddingRight="14dp"
            android:textColor="@color/colorBlack"
            android:textSize="@dimen/text_16"
            android:visibility="visible" />
        <View
            style="@style/View_o_5"
            android:layout_alignParentBottom="true" />
    </RelativeLayout>
    

    2、创建父布局的xml,activity.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <include layout="@layout/app_title" />
        <FrameLayout
            android:id="@+id/fl_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>
    

    3、都创建好了就该给BaseActivity设置布局了

    public abstract class BaseActivityNall extends AppCompatActivity {
        public TextView mBackName;
        public LinearLayout mBack;
        public TextView mTvTitle;
        public TextView mTvRight;
        public RelativeLayout mRltBase;
    
        protected View rootView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            rootView = View.inflate(this, R.layout.activity_title, null);
            setContentView(getLayoutId());
            addContent();
            setContentView(rootView);
        }
        private void addContent() {
            mBackName = (TextView) rootView.findViewById(R.id.back_name);
            mBack = (LinearLayout) rootView.findViewById(R.id.back);
            mTvTitle = (TextView) rootView.findViewById(R.id.tv_title);
            mTvRight = (TextView) rootView.findViewById(R.id.tv_right);
            mRltBase = (RelativeLayout) rootView.findViewById(R.id.rlt_base);
            FrameLayout flContent = (FrameLayout) rootView.findViewById(R.id.fl_content);
    
            mTvTitle.setText(getContentTitle() == null ? "" : getContentTitle());
            mBack.setOnClickListener(v -> finish());//java8写法,特此备注一下
    
            View content = View.inflate(this, getLayoutId(), null);
            if (content != null) {
                FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
                        FrameLayout.LayoutParams.MATCH_PARENT);
                flContent.addView(content, params);
                ButterKnife.bind(this, rootView);
            }
        }
        /**
         * 获取布局ID
         *
         * @return
         */
        protected abstract int getLayoutId();
        /**
         * title赋值
         *
         * @return
         */
        protected abstract String getContentTitle();
    }
    
    7、仿IOS侧滑finish页面实现

    实现侧滑会有很多弊端,在此就不细讲实现方式了,给大家演示一种,但是想完美实现还需进一步完善,第三方库实现,方法在BaseActivity写

    implementation 'com.r0adkll:slidableactivity:2.0.6'
    
    /**
         * 初始化滑动返回
         */
        protected void initSlidable() {
            int isSlidable = SettingUtil.getInstance().getSlidable();
            if (isSlidable != Constants.SLIDABLE_DISABLE) {
                SlidrConfig config = new SlidrConfig.Builder()
                        .edge(isSlidable == Constants.SLIDABLE_EDGE)
                        .build();
                slidrInterface = Slidr.attach(this, config);
            }
        }
      @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            initSlidable();
        }
    
    // Base application theme. 
        <style name="MyAppTheme" parent="Theme.AppCompat.Light.NoActionBar">
            <!-- Customize your theme here. -->
           // <item name="android:windowAnimationStyle">@style/activityAnimation</item>
    
            <item name="android:windowIsTranslucent">true</item>
            <!--<item name="android:windowDisablePreview">true</item>-->
            <item name="android:windowBackground">@android:color/transparent</item>
        </style>
    
    
    有很多类似的开源框架 暂举四个
    1. SwipeBackLayout
    2. Slidr
    3. Snake
    4. and_swipeback
    8、Loading页面统一实现(可替换成骨架图)

    看了一个大神写的一个框架,超级来感觉呀 spruce-android,在BaseActivity封装简单的给大家演示下,具体封装大家去实现

    /**
     * File descripition: activity基类
     * <p>
     *
     * @author lp
     * @date 2018/5/16
     */
    public abstract class BaseActivityNall extends AppCompatActivity implements BaseView {
        public TextView mBackName;
        public LinearLayout mBack;
        public TextView mTvTitle;
        public TextView mTvRight;
        public RelativeLayout mRltBase;
    
        public int mIndex = BaseContent.baseIndex;
    
        protected View rootView;
        protected LoadService mBaseLoadService;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            rootView = View.inflate(this, R.layout.activity_title, null);
            setContentView(getLayoutId());
            addContent();
            setContentView(rootView);
    
            this.initData();
            this.getData();
    
        }
    
        private void addContent() {
            mBackName = (TextView) rootView.findViewById(R.id.back_name);
            mBack = (LinearLayout) rootView.findViewById(R.id.back);
            mTvTitle = (TextView) rootView.findViewById(R.id.tv_title);
            mTvRight = (TextView) rootView.findViewById(R.id.tv_right);
            mRltBase = (RelativeLayout) rootView.findViewById(R.id.rlt_base);
            FrameLayout flContent = (FrameLayout) rootView.findViewById(R.id.fl_content);
    
            mTvTitle.setText(getContentTitle() == null ? "" : getContentTitle());
            mBack.setOnClickListener(v -> finish());//java8写法,特此备注一下
    
            View content = View.inflate(this, getLayoutId(), null);
            if (content != null) {
                FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
                        FrameLayout.LayoutParams.MATCH_PARENT);
                flContent.addView(content, params);
                ButterKnife.bind(this, rootView);
                mBaseLoadService = LoadSir.getDefault().register(content, new Callback.OnReloadListener() {
                    @Override
                    public void onReload(View v) {
                        onNetReload(v);
                    }
                });
            }
        }
        protected void onNetReload(View v) {
            mBaseLoadService.showCallback(LoadingCallback.class);
            mIndex = BaseContent.baseIndex;
            getData();
        }
        /**
         * 获取布局ID
         *
         * @return
         */
        protected abstract int getLayoutId();
        /**
         * title赋值
         *
         * @return
         */
        protected abstract String getContentTitle();
        /**
         * 数据初始化操作
         */
        protected abstract void initData();
        /**
         * 请求数据
         */
        protected abstract void getData();
    }
    
    9、点击Edittext弹出软键盘,点击空白区域让软键盘消失

    在我们使用Edittext时,软键盘弹出了,写完字之后,想让它消失,不去处理想让软键盘消失需要点击软键盘中的消失按钮,显然不是很方便的方法,我们想点击非Edittext任何地方都让软键盘(也可以点击Edittext让软键盘消失),请往下看,有俩种实现方法
    (1)、第一种实现方法,扩展性差

    @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
                View v = getCurrentFocus();
                if (isShouldHideKeyboard(v, ev)) {
                    hideKeyboard(v.getWindowToken());
                }
            }
            return super.dispatchTouchEvent(ev);
        }
    
        /**
         * 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘,因为当用户点击EditText时则不能隐藏
         *
         * @param v
         * @param event
         * @return
         */
        private boolean isShouldHideKeyboard(View v, MotionEvent event) {
            if (v != null && (v instanceof EditText)) {
                int[] l = {0, 0};
                v.getLocationInWindow(l);
                int left = l[0],
                        top = l[1],
                        bottom = top + v.getHeight(),
                        right = left + v.getWidth();
                if (event.getX() > left && event.getX() < right
                        && event.getY() > top && event.getY() < bottom) {
                    // 点击EditText的事件,忽略它。
                    return false;
                } else {
                    return true;
                }
            }
            // 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditText上,和用户用轨迹球选择其他的焦点
            return false;
        }
    
        /**
         * 获取InputMethodManager,隐藏软键盘
         *
         * @param token
         */
        private void hideKeyboard(IBinder token) {
            if (token != null) {
                InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS);
            }
        }
    

    (2)、第二种实现方法(推荐使用)

    
        /**
         * 以下是关于软键盘的处理
         */
    
        /**
         * 清除editText的焦点
         *
         * @param v   焦点所在View
         * @param ids 输入框
         */
        public void clearViewFocus(View v, int... ids) {
            if (null != v && null != ids && ids.length > 0) {
                for (int id : ids) {
                    if (v.getId() == id) {
                        v.clearFocus();
                        break;
                    }
                }
            }
        }
    
        /**
         * 隐藏键盘
         *
         * @param v   焦点所在View
         * @param ids 输入框
         * @return true代表焦点在edit上
         */
        public boolean isFocusEditText(View v, int... ids) {
            if (v instanceof EditText) {
                EditText et = (EditText) v;
                for (int id : ids) {
                    if (et.getId() == id) {
                        return true;
                    }
                }
            }
            return false;
        }
    
        //是否触摸在指定view上面,对某个控件过滤
        public boolean isTouchView(View[] views, MotionEvent ev) {
            if (views == null || views.length == 0) {
                return false;
            }
            int[] location = new int[2];
            for (View view : views) {
                view.getLocationOnScreen(location);
                int x = location[0];
                int y = location[1];
                if (ev.getX() > x && ev.getX() < (x + view.getWidth())
                        && ev.getY() > y && ev.getY() < (y + view.getHeight())) {
                    return true;
                }
            }
            return false;
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
                if (isTouchView(filterViewByIds(), ev)) {
                    return super.dispatchTouchEvent(ev);
                }
                if (hideSoftByEditViewIds() == null || hideSoftByEditViewIds().length == 0) {
                    return super.dispatchTouchEvent(ev);
                }
                View v = getCurrentFocus();
                if (isFocusEditText(v, hideSoftByEditViewIds())) {
                    KeyBoardUtils.hideInputForce(this);
                    clearViewFocus(v, hideSoftByEditViewIds());
                }
            }
            return super.dispatchTouchEvent(ev);
        }
    
    
        /**
         * 传入EditText的Id
         * 没有传入的EditText不做处理
         *
         * @return id 数组
         */
        public int[] hideSoftByEditViewIds() {
            return null;
        }
    
        /**
         * 传入要过滤的View
         * 过滤之后点击将不会有隐藏软键盘的操作
         *
         * @return id 数组
         */
        public View[] filterViewByIds() {
            return null;
        }
    
    

    使用方法:在对应的Activity重写hideSoftByEditViewIds()和filterViewByIds(),传入需要弹出的软键盘的ID

     /*实现案例===============================================================================================*/
    
        @Override
        public int[] hideSoftByEditViewIds() {
            int[] ids = {R.id.et_company_name, R.id.et_address};
            return ids;
        }
    
        @Override
        public View[] filterViewByIds() {
            View[] views = {mEtCompanyName, mEtAddress};
            return views;
        }
    
    
    10、结合MVP模式下的BaseActivity,传送地址
    /**
     * File descripition: activity基类
     * <p>
     *
     * @author lp
     * @date 2018/5/16
     */
    public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements BaseView {
        protected final String TAG = this.getClass().getSimpleName();
        public View mViewStatusBar;
        public TextView mBackName;
        public LinearLayout mBack;
        public TextView mTvTitle;
        public TextView mTvRight;
        public RelativeLayout mRltBase;
    
        public Activity mContext;
        protected P mPresenter;
    
        private LoadingDialog mLodingDialog;
    
        protected abstract P createPresenter();
    
        //错误提示框  警告框  成功提示框
        private PromptDialog promptDialog;
    
        public int mIndex = BaseContent.baseIndex;
    
        protected View rootView;
        protected LoadService mBaseLoadService;
    
        /**
         * 是否显示初始Loading
         */
        private Boolean isShow = false;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//设置竖屏模式
            mContext = this;
            rootView = View.inflate(this, R.layout.activity_title, null);
            setContentView(getLayoutId());
            addContent();
            setContentView(rootView);
            mPresenter = createPresenter();
            AppManager.getAppManager().addActivity(this);
            setStatusBar();
            initAppStatus();
            ButterKnife.bind(this);
    
            this.initData();
    
        }
    
        private void initAppStatus() {
            switch (AppStatusManager.getInstance().getAppStatus()) {
                /**
                 * 应用被强杀
                 */
                case AppStatusConstant.STATUS_FORCE_KILLED:
                    //跳到主页,主页lauchmode SINGLETASK
                    protectApp();
                    break;
            }
        }
    
        private void addContent() {
            mViewStatusBar = (View) rootView.findViewById(R.id.view_status_bar);
            mBackName = (TextView) rootView.findViewById(R.id.back_name);
            mBack = (LinearLayout) rootView.findViewById(R.id.back);
            mTvTitle = (TextView) rootView.findViewById(R.id.tv_title);
            mTvRight = (TextView) rootView.findViewById(R.id.tv_right);
            mRltBase = (RelativeLayout) rootView.findViewById(R.id.rlt_base);
            FrameLayout flContent = (FrameLayout) rootView.findViewById(R.id.fl_content);
    
            mTvTitle.setText(getContentTitle() == null ? "" : getContentTitle());
            mBack.setOnClickListener(v -> finish());
    
            View content = View.inflate(this, getLayoutId(), null);
            if (content != null) {
                FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
                        FrameLayout.LayoutParams.MATCH_PARENT);
                flContent.addView(content, params);
                ButterKnife.bind(this, rootView);
                mBaseLoadService = LoadSir.getDefault().register(content, new Callback.OnReloadListener() {
                    @Override
                    public void onReload(View v) {
                        showLoadingLayout();
                        mIndex = BaseContent.baseIndex;
                        getData();
                    }
                });
                if (isShow) {
                    showLoadingLayout();
                } else {
                    PostUtil.postSuccessDelayed(mBaseLoadService, 0);
                }
            }
        }
    
        protected void protectApp() {
            Intent intent = new Intent(this, MainActivity.class);
            intent.putExtra(AppStatusConstant.KEY_HOME_ACTION, AppStatusConstant.ACTION_RESTART_APP);
            startActivity(intent);
        }
    
        private void showLoadingLayout() {
            mBaseLoadService.showCallback(LoadingCallback.class);
        }
    
        public void showLoadingLayout(boolean isShow) {
            this.isShow = isShow;
        }
    
        /**
         * 获取布局ID
         *
         * @return
         */
        protected abstract int getLayoutId();
    
        /**
         * title赋值
         *
         * @return
         */
    
        protected abstract String getContentTitle();
    
        /**
         * 数据初始化操作
         */
        protected abstract void initData();
    
        /**
         * 请求数据
         */
        protected abstract void getData();
    
        /**
         * 沉浸式实现
         */
        protected void setStatusBar() {
            StatusBarUtil.setColor(this, getResources().getColor(R.color.colorWhite), 0);
    //        StatusBarUtil.setTranslucentForImageViewInFragment(this, 0, null);
        }
    
        public void showToast(String str) {
            showToast(str, Toast.LENGTH_SHORT);
        }
    
        public void showLongToast(String str) {
            showToast(str, Toast.LENGTH_LONG);
        }
    
        /**
         * 封装toast方法
         *
         * @param str
         * @param dur
         */
        void showToast(String str, int dur) {
            ToastUtils.showToastS(this, str, dur);
        }
    
        @Override
        public void showError(String msg) {
            showToast(msg);
        }
    
        @Override
        public void onErrorCode(BaseModel model) {
            if (model.getErrcode() == BaseObserver.NETWORK_ERROR) {//网络连接失败  无网
                PostUtil.postCallbackDelayed(mBaseLoadService, NetWorkErrorCallback.class);
            } else if (model.getErrcode() == BaseObserver.CONNECT_ERROR ||//连接错误
                    model.getErrcode() == BaseObserver.CONNECT_TIMEOUT ||//连接超时
                    model.getErrcode() == BaseObserver.BAD_NETWORK ||//网络超时
                    model.getErrcode() == BaseObserver.CONNECT_NULL//数据为空,显示异常
                    ) {
                PostUtil.postCallbackDelayed(mBaseLoadService, ErrorCallback.class);
            } else if (model.getErrcode() == BaseObserver.CONNECT_NOT_LOGIN) {//没有登录,去登录
                startLogin();
            }
        }
    
        private void startLogin() {
            AppUMS.mIsLogin = false;
            AppUMS.setToken("");
            startActivity(LoginActivity.class);
        }
        @Override
        public void showLoading() {
            showLoadingDialog();
        }
        @Override
        public void hideLoading() {
            closeLoadingDialog();
        }
        public void closeLoadingDialog() {
            if (mLodingDialog != null && mLodingDialog.isShowing()) {
                mLodingDialog.dismiss();
            }
        }
        /**
         * 加载...
         */
        public void showLoadingDialog() {
            if (mLodingDialog == null) {
                mLodingDialog = new LoadingDialog(this).setMessage(getString(R.string.app_loding));
            }
            mLodingDialog.show();
        }
        /**
         * 警告框
         */
        public void showInfoDialog(String msg) {
            if (promptDialog == null) {
                promptDialog = new PromptDialog(this);
            }
            promptDialog.showInfo(msg);
        }
        /**
         * 错误提示框
         */
        public void showErrorDialog(String msg) {
            if (promptDialog == null) {
                promptDialog = new PromptDialog(this);
            }
            promptDialog.showError(msg);
        }
        /**
         * 成功提示框
         */
        public void showSuccessDialog(String msg) {
            if (promptDialog == null) {
                promptDialog = new PromptDialog(this);
            }
            promptDialog.showSuccess(msg);
        }
        @Override
        protected void onResume() {
            super.onResume();
            MobclickAgent.onResume(this);
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            MobclickAgent.onPause(this);
        }
        @Override
        protected void onDestroy() {
            super.onDestroy();
            ButterKnife.bind(this).unbind();
            AppManager.getAppManager().finishActivity(this);
            if (mPresenter != null) {
                mPresenter.detachView();
            }
        }
    
        @Override
        public boolean dispatchKeyEvent(KeyEvent event) {
            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
                    && event.getAction() == KeyEvent.ACTION_DOWN) {
                finishActivity();
                return false;
            }
            return super.dispatchKeyEvent(event);
        }
        public void finishActivity() {
            finish();
        }
        /**
         * [页面跳转]
         *
         * @param clz
         */
        public void startActivity(Class<?> clz) {
            startActivity(clz, null);
        }
        /**
         * [携带数据的页面跳转]
         *
         * @param clz
         * @param bundle
         */
        public void startActivity(Class<?> clz, Bundle bundle) {
            Intent intent = new Intent();
            intent.setClass(this, clz);
            if (bundle != null) {
                intent.putExtras(bundle);
            }
            startActivity(intent);
        }
        /**
         * [含有Bundle通过Class打开编辑界面]
         *
         * @param cls
         * @param bundle
         * @param requestCode
         */
        public void startActivityForResult(Class<?> cls, Bundle bundle, int requestCode) {
            Intent intent = new Intent();
            intent.setClass(this, cls);
            if (bundle != null) {
                intent.putExtras(bundle);
            }
            startActivityForResult(intent, requestCode);
        }
        /**
         * 以下是关于软键盘的处理
         */
        /**
         * 清除editText的焦点
         *
         * @param v   焦点所在View
         * @param ids 输入框
         */
        public void clearViewFocus(View v, int... ids) {
            if (null != v && null != ids && ids.length > 0) {
                for (int id : ids) {
                    if (v.getId() == id) {
                        v.clearFocus();
                        break;
                    }
                }
            }
        }
    
        /**
         * 隐藏键盘
         *
         * @param v   焦点所在View
         * @param ids 输入框
         * @return true代表焦点在edit上
         */
        public boolean isFocusEditText(View v, int... ids) {
            if (v instanceof EditText) {
                EditText et = (EditText) v;
                for (int id : ids) {
                    if (et.getId() == id) {
                        return true;
                    }
                }
            }
            return false;
        }
        //是否触摸在指定view上面,对某个控件过滤
        public boolean isTouchView(View[] views, MotionEvent ev) {
            if (views == null || views.length == 0) {
                return false;
            }
            int[] location = new int[2];
            for (View view : views) {
                view.getLocationOnScreen(location);
                int x = location[0];
                int y = location[1];
                if (ev.getX() > x && ev.getX() < (x + view.getWidth())
                        && ev.getY() > y && ev.getY() < (y + view.getHeight())) {
                    return true;
                }
            }
            return false;
        }
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
                if (isTouchView(filterViewByIds(), ev)) {
                    return super.dispatchTouchEvent(ev);
                }
                if (hideSoftByEditViewIds() == null || hideSoftByEditViewIds().length == 0) {
                    return super.dispatchTouchEvent(ev);
                }
                View v = getCurrentFocus();
                if (isFocusEditText(v, hideSoftByEditViewIds())) {
                    KeyBoardUtils.hideInputForce(this);
                    clearViewFocus(v, hideSoftByEditViewIds());
                }
            }
            return super.dispatchTouchEvent(ev);
        }
        /**
         * 传入EditText的Id
         * 没有传入的EditText不做处理
         *
         * @return id 数组
         */
        public int[] hideSoftByEditViewIds() {
            return null;
        }
        /**
         * 传入要过滤的View
         * 过滤之后点击将不会有隐藏软键盘的操作
         *
         * @return id 数组
         */
        public View[] filterViewByIds() {
            return null;
        }
        /*实现案例===============================================================================================*/
        /*
        @Override
        public int[] hideSoftByEditViewIds() {
            int[] ids = {R.id.et_company_name, R.id.et_address};
            return ids;
        }
        @Override
        public View[] filterViewByIds() {
            View[] views = {mEtCompanyName, mEtAddress};
            return views;
        }
        */
    }
    

    最后,祝大家开发顺利!

    相关文章

      网友评论

        本文标题:浅谈BaseActivity写法,促使我们更高效开发

        本文链接:https://www.haomeiwen.com/subject/sjnhlqtx.html