Android App框架設計 基類BaseActivity

Android App框架設計 基類BaseActivity

這個基類是自己封裝的,不是很完善,之前一直打算寫博客
卻一直沒動手

效果

這裏寫圖片描述
這裏進行先斷網,再測試,可以看到界面切換的三個狀態

1.概述

項目中最常見的界面不外乎 標題欄加上具體內容

標題欄:返回按鈕 + 標題 + 菜單按鈕

具體內容:需要考慮考慮加載狀態

這就可以考慮進行封裝了,還有一個方法,常用成員變量也可以考慮封裝到基類中,方便使用

本基類主要封裝內容

1.DataBinding避免findViewById

2.toolbar滿足基本要求的封裝

3.Activity管理類綁定生命週期

4.界面加載狀態切換管理類封裝

5.一些常用資源聲明爲成員變量到基類

代碼

BaseActivity傳入泛型,主要用於DataBinding綁定xml

`public abstract class BaseActivity<T extends ViewDataBinding> extends AppCompatActivity implements View.OnClickListener {`

成員變量

`/**
 * DataBinding 對象
 */
protected T mBinding;
/**
 * 界面狀態切換 對象
 */
protected VaryViewHelper mHelper;
/**
 * 本Actvitiy類名
 */
protected static String ACTIVITY_NAME;
/**
 * onCreate方法中保存的數據
 */
protected Bundle savedInstanceState;
/**
 * 上下文
 */
protected Activity context;
/**
 * 全局上下文 ,這裏進行了強轉,需要注意自己的Application實際類名
 */
protected App application;
/**
 * 屏幕寬,高, 狀態欄高
 */
protected int screenWidth, screenHeight, statusBarHeightX;`

主要onCreate初始化

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.savedInstanceState = savedInstanceState;
    LogUtils.i(ACTIVITY_NAME = getClass().getSimpleName());
    context = this;
    application = (App) getApplication();
    screenWidth = ScreenUtils.getScreenWidthPixels(getActivity());
    screenHeight = ScreenUtils.getScreenHeightPixels(getActivity());
    statusBarHeightX = ScreenUtils.getStatusHeight(getActivity());

    ActivityCollector.addActivity(this); //添加進activity管理
    mBinding= DataBindingUtil.setContentView(this,setLayoutId()); //獲取DataBinding對象
    initToolBar();
    initView();
    initListener();
    mHelper = new VaryViewHelper.Builder()  //初始化界面狀態管理器 ,需要自己寫幾類佈局
            .setDataView(findViewById(getRootId()))
            .setLoadingView(LayoutInflater.from(this).inflate(R.layout.layout_loadingview,
                    null))//加載頁,無實際邏輯處理
            .setEmptyView(LayoutInflater.from(this).inflate(R.layout.layout_emptyview,
                    null))//空頁面,無實際邏輯處理
            .setErrorView(
                    LayoutInflater.from(this).inflate(R.layout.layout_errorview, null))//錯誤頁面
            .setRefreshListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mHelper.showLoadingView();
                    getData();
                }
            })
            .build();
    mHelper.showLoadingView();
    getData();
}

主要進行類DataBinding綁定佈局,初始化界面管理類,初始化toolbar等

下面是抽象出來的必須實現的方法

  /**
 * 設置佈局 layout 的 資源id
 */
protected abstract int setLayoutId();

/**
 *設置除了toolbar 以外的 內容佈局content的id ,防止toolbar在頁面狀態切換時被覆蓋
 */
protected abstract int getRootId();
/**
 * 初始化ToolBar
 */
protected abstract void initToolBar();
/**
 * 初始化一些非加載數據相關的view
 */
protected abstract void initView();
/**
 * 初始化監聽
 */
protected abstract void initListener();

/**
 * 獲取網絡數據,獲取數據後也在這裏更新數據
 */
protected abstract void getData();

/**
 * BaseActivity已經實現了OnClickListener 接口 ,這裏進行了空實現,防止部分界面不需要點擊事件,也就不需要實現
 * 如果需要直接重寫該方法
 */
@Override
public void onClick(View v) {

}

其他工具類 及onDestroy方法接觸Activity管理類的管理
@Override
public void onBackPressed() {
finish();
}

@Override
protected void onDestroy() {
    ActivityCollector.removeActivity(this);
    super.onDestroy();
}

/**
 * Toast工具類
 */
public Toast toast;
public void showToast(String text) {
    if (toast == null) {
        toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
    } else {
        toast.setText(text);
    }
    toast.show();
}

public void showToast(BaseActivity activity, String text) {
    if (toast == null) {
        toast = Toast.makeText(activity, text, Toast.LENGTH_SHORT);
    } else {
        toast.setText(text);
    }
    toast.show();
}

public void showToast(int textId) {
    showToast(getString(textId));
}

public BaseActivity getActivity() {
    return this;
}

public Intent getIntent(Class clazz) {
    return new Intent(context, clazz);
}

public void startIntent(Class clazz) {
    startActivity(getIntent(clazz));
}

public int dp2px(int dp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
            context.getResources().getDisplayMetrics());
}

protected void hideStatusBar() {
    int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;//隱藏狀態欄, 定義全屏參數
    Window window = getWindow(); //獲得當前窗體對象
    window.setFlags(flag, flag);//設置當前窗體爲全屏顯示
}

private long lastClickTime;
/**
 * 實現連續點擊兩次才退出應用程序
 */
public void exit() {
    if ((System.currentTimeMillis() - lastClickTime) > 2000) {
        showToast("再按一次退出" + context.getResources().getString(R.string.app_name));
        lastClickTime = System.currentTimeMillis();
    } else {
        ActivityCollector.removeAll();
        System.exit(0);
    }
}

不需要的工具方法可以刪除

其他資源及注意點

toolbar

本基類包含初始化Toolbar內容,旨在統一風格
使用ToolBar需要給Activity配上style
主要加上這兩條屬性

  <item name="android:windowNoTitle">true</item>
    <item name="android:windowActionBar">false</item>

佈局文件中必須包含Toolbar
然後在initToolBar實現中進行設置ToolBar

activity_main.xml

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

</LinearLayout>
</LinearLayout>
</layout>

layout_toolbar.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/id_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:popupTheme="@style/ToolbarPopupTheme"
android:background="@color/colorPrimary"
android:minHeight="?attr/actionBarSize">
<TextView
    android:id="@+id/toolbar_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:singleLine="true"
    android:textColor="@android:color/white"
    android:textSize="18sp"/>
</android.support.v7.widget.Toolbar>
</layout>

對於toolbar中的menu實現類中進行加載

    @Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater menuInflater = getMenuInflater();
    menuInflater.inflate(R.menu.menu_item_four, menu);
    menu
            .findItem(R.id.item1)
            .setVisible(true);
    menu.findItem(R.id.item2)
            .setVisible(true);
    menu.findItem(R.id.item3)
            .setVisible(true);
    return true;
}

res/menu/menu_item_four.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:visible="false"
    android:id="@+id/item1"
    android:title="菜單1"/>

<item
    android:visible="false"
    android:id="@+id/item2"
    android:title="菜單2"/>
<item
    android:visible="false"
    android:id="@+id/item3"
    android:title="菜單3"/>

<item
    android:visible="false"
    android:id="@+id/item4"
    android:title="菜單4"/>

</menu>

完整實現類

public class MainActivity extends BaseActivity<ActivityMainBinding> {

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater menuInflater = getMenuInflater();
    menuInflater.inflate(R.menu.menu_item_four, menu);
    menu
            .findItem(R.id.item1)
            .setVisible(true);
    menu.findItem(R.id.item2)
            .setVisible(true);
    menu.findItem(R.id.item3)
            .setVisible(true);
    return true;
}

@Override
protected void initToolBar() {
    mBinding.includeToolbar.idToolbar.setTitle("");
    mBinding.includeToolbar.toolbarTitle.setText("mainactivity");
    setSupportActionBar(mBinding.includeToolbar.idToolbar);
    ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
}

@Override
protected void initView() {

}

@Override
protected void initListener() {
    mBinding.btn.setOnClickListener(this);
}

@Override
protected int setLayoutId() {  //傳入layout佈局
    return R.layout.activity_main;
}

@Override
protected int getRootId() {  //傳入佈局中除去toolbar部分的佈局id
    return R.id.content_main;  
}

@Override
protected void getData() {
    //網絡請求
    OkHttpUtils
            .get()
            .url("http://gank.io/api/data/Android/10/1")
            .build()
            .execute(new GankCallback() {


                @Override
                public void requestError(Call call, Exception e, int id) {
                     mHelper.showErrorView();//切換加載錯誤界面
                }

                @Override
                public void onResponse(String response, int id) {
                    mBinding.tv.setText(response);
                    mHelper.showDataView();//切換正常界面
                }
            });
}

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.btn:

            break;
    }
}
}

需要注意的是 基類初始化 只是初試標題欄等不需要網絡數據的部分
在onCreate最後調用getData獲取網絡數據前,已經切換頁面爲加載狀態
需要在getData實現類中切換回來

因爲加載狀態時 希望標題欄不被加載界面覆蓋,這裏的getRootId實現類傳入主體內容容器id,不包含toolbar

ActivityCollector

activity管理類

/**
 Desc: activity管理類
 */
public class ActivityCollector {
public static List<Activity> activitys = new ArrayList<>();
public static void addActivity(Activity activity) {
    activitys.add(activity);//把傳入的Activity添加到List中
}
public static void removeActivity(Activity activity) {
    activitys.remove(activity);//根據傳入的Activity來刪除
}
public static void removeAll() {
    for (Activity activity : activitys) {
        if (!activity.isFinishing()) {
            activity.finish();
        }
    }
}
/**
     除了傳來的Activity其他的全部刪除
可以傳多個Activity

 */
public static void removeAll(Class<?>... clazz) {
    boolean isExist = false;
    for (Activity act : activitys) {
        for (Class c : clazz) {
            if (act.getClass().isAssignableFrom(c)) {
                isExist = true;
                break;
            }
        }
        if (!isExist) {
            if (!act.isFinishing()) {
                act.finish();
            }
        } else {
            isExist = false;
        }
    }
}
/**
  從Activity集合查詢, 傳入的Activity是否存在
  如果存在就返回該Activity,不存在就返回null
 */
public static Activity getActivity(Class<?> activity) {
    for (int i = 0; i < activitys.size(); i++) {
        // 判斷是否是自身或者子類
        if (activitys.get(i).getClass().isAssignableFrom(activity)) {
            return activitys.get(i);
        }
    }
    return null;
}


public static Activity getTopActivity() {
    return activitys.get(activitys.size()-1);
}

}

Demo下載地址

http://download.csdn.net/detail/jiushiwo12340/9852351

參考內容

基於 Android在開發中的實用技巧之BaseActivity

基於DataBinding

基於 Activity加載網絡數據切換狀態工具

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章