美文网首页1-Android开发知识
Android搭建应用框架系列之BaseActivity

Android搭建应用框架系列之BaseActivity

作者: Goach | 来源:发表于2017-11-17 18:06 被阅读160次

    前言

    其实写BaseActivity的时候,都需要结合不同的App的需求以及应用架构来实现的,没有固定的实现方式。所以这里结合前面几篇文章来写一个BaseActivity

    思路

    结合前面的文章说的,BaseActivity应该有下面这些内容

    • IProgressDialog接口的实现,实现加载框动画
    • FragmentManager 方便操作Fragment使用
    • CompositeDisposable 网络绑定和解绑在BaseActivity的生命周期里面统一处理
    • RealmRealmAsyncTask Realm的实例和异步处理通知监听事件结合BaseActivity的生命周期处理
    • ToolBar 统一处理应用的ToolBar
    • initViewinitListener两个模板方法

    ProgressDialog

    应用中往往少不了加载动画,所以BaseActivity也应该写一个公共的显示和隐藏加载框的方法,结合前文的IProgressDialog接口。由于AndroidProgressDialog注解过时,Google不推荐使用,那么这里就通过AlertDialog+ProgressBar简单实现下面的效果

    加载框.png

    我们都知道AlertDialog是有一个底色背景的,所以这里先写一个Style让底色背景透明

     <style name="ProgressDialog" parent="Theme.AppCompat.Dialog">
            <item name="android:backgroundDimEnabled">false</item>
            <item name="android:windowBackground">@android:color/transparent</item>
     </style>
    

    接下来就是这个弹框的布局

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/progress_shape"
        android:gravity="center"
        android:orientation="vertical">
    
        <ProgressBar
            android:id="@+id/iv_pb"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp" />
    
        <TextView
            android:id="@+id/tv_tip"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:layout_marginEnd="20dp"
            android:layout_marginStart="20dp"
            android:layout_marginTop="10dp"
            android:gravity="center"
            android:text="加载中..."
            android:textColor="@android:color/white"
            android:textSize="16sp" />
    </LinearLayout>
    

    然后就是创建AlertDialog设置布局

    object AlertDialogUtils {
        private var mAlertDialog:AlertDialog? = null
        @SuppressLint("InflateParams")
        fun showProgressDialog(context: Context,tip:String = ""){
            if(mAlertDialog==null)
                mAlertDialog = AlertDialog.Builder(context,R.style.ProgressDialog).create()
            val loadView = context.layoutInflater.inflate(R.layout.alert_progress,null)
            mAlertDialog!!.setView(loadView,0,0,0,0)
            mAlertDialog!!.setCanceledOnTouchOutside(false)
            mAlertDialog!!.show()
            if(TextUtils.isEmpty(tip).not())
            loadView.find<TextView>(R.id.tv_tip).text = tip
        }
        fun dismiss(){
            if(mAlertDialog!=null&&mAlertDialog!!.isShowing)
                mAlertDialog?.dismiss()
        }
    }
    

    把前面的Style在创建AlertDialog.Builder()传入即可让底色背景透明,然后通过AlertDialogsetView()方法就可以自定义布局了。

    FragmentManager

    val fm: FragmentManager by lazy(LazyThreadSafetyMode.NONE) { supportFragmentManager }
    

    定义一个FragmentManager方便操作Fragment的时候使用

    CompositeDisposable

    对应Rx1.x版本的CompositeSubscription,将请求接口统一绑定起来

    val sub = CompositeSubscription()
    

    然后在onDestroy()进行统一的解绑

     override fun onDestroy() {
            sub.clear()
            super.onDestroy()
        }
    

    Realm

    结合前文封装的RealmHelper帮助类,实现Realm的实例并且定义一个RealmAsyncTask

    val mRealm = RealmHelper.getRealmInstance(AppRealmMigrateImpl())
    val mRealmAsyncList = mutableListOf<RealmAsyncTask>()
    

    然后在onStop里面进行清除

    override fun onStop() {
            mRealmAsyncList.forEach {
                if(!it.isCancelled) it.cancel()
            }
            mRealmAsyncList.clear()
            super.onStop()
    }
    

    ToolBar

    首先会在BaseActivity定义一个默认的布局act_single_fragment.xml

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <FrameLayout
            android:id="@+id/content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="?attr/actionBarSize" />
        <include layout="@layout/toolbar_layout" />
    </FrameLayout>
    

    其中content是用来放置内容的区域,然后toolbar_layout.xmlToolBar的布局

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        app:elevation="0dp">
    
        <android.support.v7.widget.Toolbar
            android:id="@+id/tool_bar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:foreground="@android:color/transparent"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Dark"
            app:contentInsetStart="5dp">
    
            <FrameLayout
                android:id="@+id/custom_view"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"/>
    
        </android.support.v7.widget.Toolbar>
    </android.support.design.widget.AppBarLayout>
    
    

    提供一个方法供外部实现ToolBar样式,默认是TitleFragment

     open fun toolbarCustomView(): Fragment? = TitleFragment()
    

    TitleFragment就是一个简单的头部样式,如图

    ToolBar.png
    class TitleFragment : BaseFragment(){
        var onBackListener:BackClickListener? = null
        override fun layoutResID()= R.layout.toolbar_title_layout
        override fun initView(view: View) {
            super.initView(view)
            tvTitle.text = activity.title
        }
    
        override fun initListener() {
            super.initListener()
            ivBack.onClick {
                onBackListener?.onBack(ivBack)
            }
        }
        fun setTitle(title: CharSequence?) {
            tvTitle?.text = title
        }
        interface BackClickListener{
            fun onBack(view:View)
        }
    }
    

    最后处理返回键的回调方法

     private fun configToolBar(){
            supportActionBar?.setDisplayShowTitleEnabled(false)
             toolbarCustomView()?.apply{
                 mToolBarLayout = this
                 fm.beginTransaction().replace(R.id.custom_view, this).commitAllowingStateLoss()
                 (this as? TitleFragment)?.apply {
                     this.onBackListener = object:TitleFragment.BackClickListener{
                         override fun onBack(view: View) {
                             onBackClick(view)
                         }
                     }
                 }
             }
        }
    

    BaseActivity

    通过上面的说明,最终BaseActivity如下

    abstract class BaseActivity:AppCompatActivity(), IProgressDialog {
        val fm: FragmentManager by lazy(LazyThreadSafetyMode.NONE) { supportFragmentManager }
        val sub = CompositeDisposable()
        val mRealm = RealmHelper.getRealmInstance(AppRealmMigrateImpl())
        val mRealmAsyncList = mutableListOf<RealmAsyncTask>()
        private val mToolBar by lazy { findOptional<Toolbar>(R.id.tool_bar) }
        private var mToolBarLayout:Fragment? = null
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            val layoutResID = layoutResID()
            if(layoutResID>0){
                setContentView(layoutResID)
            }
            val layoutView = layoutView()
            if(layoutView!=null){
                setContentView(layoutView)
            }
            if(mToolBar!=null){
                setSupportActionBar(mToolBar)
                configToolBar()
            }
            if (!isFinishing) {
                initView()
            }
            if (!isFinishing) {
                initListener()
            }
        }
        protected open fun initView() {
        }
    
        protected open fun initListener() {
        }
        @LayoutRes open fun layoutResID():Int = R.layout.act_single_fragment
        open fun layoutView(): View? = null
        open fun toolbarCustomView(): Fragment? = TitleFragment()
        open fun onBackClick(v: View?) = finish()
        private fun configToolBar(){
            supportActionBar?.setDisplayShowTitleEnabled(false)
             toolbarCustomView()?.apply{
                 mToolBarLayout = this
                 fm.beginTransaction().replace(R.id.custom_view, this).commitAllowingStateLoss()
                 (this as? TitleFragment)?.apply {
                     this.onBackListener = object:TitleFragment.BackClickListener{
                         override fun onBack(view: View) {
                             onBackClick(view)
                         }
                     }
                 }
             }
        }
    
        override fun showLoading() {
            AlertDialogUtils.showProgressDialog(this)
        }
    
        override fun dismissLoading() {
            AlertDialogUtils.dismiss()
        }
    
        override fun updateNextPage(haveNext: Boolean) {
    
        }
        override fun setTitle(title: CharSequence?) {
            super.setTitle(title)
        }
    
        override fun setTitle(titleId: Int) {
            title = getString(titleId)
        }
    
        override fun onStop() {
            mRealmAsyncList.forEach {
                if(!it.isCancelled) it.cancel()
            }
            mRealmAsyncList.clear()
            super.onStop()
        }
        override fun onDestroy() {
            sub.clear()
            super.onDestroy()
        }
    }
    

    相关文章

      网友评论

        本文标题:Android搭建应用框架系列之BaseActivity

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