個人博客CoorChice,https://chenbingx.github.io/ ,最新文章將會首發CoorChice的博客,歡迎探索哦 !
同時,搜索微信公眾號CoorChice
,或掃描文章末尾二維碼,可以關注我的微信公眾號。同期文章也將會優先推送到微信公眾號中,以提醒您有新鮮文章出爐。
本系列文章列表
通過前面幾篇你已經準備好,可以開始輸入代碼,創建你的應用了。
App初始化
我們要自定義Application
默認情況下,系統會讓你的應用使用默認的Application,可以,這很方便。但是實際開發中,我們往往需要在應用程序一進去就開始一些初始化(初始化配置、加載后面要使用的資源)的操作,所以我們需要使用自己的Application。
- 首先extends Application,目前暫時只在其中初始化異常捕捉
public class ChiceApplication extends Application {
private static Context context;
@Override
public void onCreate() {
super.onCreate();
context = this;
// 初始化異常處理類
CrashHandler.getInstance().init(context);
}
//獲取系統級Context
public static Context getAppContext(){
return context;
}
}
- 在AndroidManifest.xml中把
<application>
標簽的name屬性改成我們定義的這個Application。接下來,我們每次啟動應用時,系統將初始化我們的ChiceApplication
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.chenbing.oneweather">
<application
android:name=".ChiceApplication" //就是在這里修改為我們的Application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".View.activitys.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
編寫基類
Activity基類
我們的Activity繼承自v7兼容包下的AppComponentActivity。由于v7包提供了更多的特性,并且當今時代,我們并不需要考慮android 2.1之前的兼容性,試問你聽說過有誰在用2.1之前的Android機嗎?有的用戶可能喜歡刷機,但是網上的ROM也基本都是基于android 2.1以上,所以我就直接使用v7兼容包了。
//我們后續創建的Activity都需要繼承這個BaseActivity,這樣便于以后植入統一的操作。
//不然以后需要統一給Activity進行相同操作時,你就要一個個去改。真蛋疼啊!
//之所以寫成抽象,是為了規范約束,提醒你下面幾個方法是必要的
public abstract class BaseActivity extends AppCompatActivity {
//初始化數據請求(不是必須的,習慣了)
abstract protected void initData();
//初始化View
abstract protected void initView();
//給View添加監聽器
abstract protected void addListener();
}
Fragment基類
Fragment我選擇繼承v4包的,因為app包下只支持4.4以上,對于現在的Android市場來說太高了。
public abstract class BaseFragment extends Fragment {
abstract protected void initData();
abstract protected void initView();
abstract protected void addListener();
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.setClickable(true); //讓Fragment最底層的View攔截事件,防止扯到蛋的點透
}
}
BaseRelativeLayout
因為我比較喜歡使用RelativeLayout,所以選擇它做View的基類。這個基類可選,主要是為了方便創建自定義View。
public abstract class BaseRelativeLayout extends RelativeLayout {
public BaseRelativeLayout(Context context) {
this(context, null);
}
public BaseRelativeLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BaseRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
bindView();
}
private void bindView() {
LayoutInflater inflater = LayoutInflater.from(getContext());
inflater.inflate(getLayout(), this, true);
ButterKnife.bind(this);
};
//重寫這個方法就能加載布局了。
abstract protected int getLayout();
}
BaseItemViewHolder
這個是專門為RecyclerView設計的ViewHolder,目的是為了簡化ViewHolder的使用。
public class BaseItemViewHolder extends RecyclerView.ViewHolder {
public BaseItemViewHolder(View itemView) {
super(itemView);
}
}
//看看RecyclerView的Adapter現在的變化
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new BaseItemViewHolder(new NavigatorItemView(context)); //一句話創建
}
設計主要架構
本項目我們采用時下流行的MVP框架,現在針對MainActtivity先來進行結構設計。設計結構時需要注意以下幾點:
- 遵循依賴倒置原則,即模塊應該依賴抽象,而不要依賴具體。這樣做的的好處是,單需求發生變化,比如Model需要切換邏輯時,我們只需要換一個實現了同一個接口的實現類就可以,而不用對Presenter修改。同樣,當我們現有的一套Presenter和Model需要在另一個View模塊上展示時,只要View模塊不要求View接口發生變化,我們可以很容易的就把這套東西用到新的View模塊上。當然,理論上可行,但實際的Android開發中往往是View模塊占據主導地位,至少大多數時候是這樣。
- 使用MVP框架其實就已經注定了代碼量會增大,所以不能為了省事把Model模塊的邏輯、算法代碼寫到Presenter中。
- 要注意我們的依賴關系。
下面看看View、Model、Presenter的結構。
View模塊
//抽象
//我們的Presenter需要依賴的就是這個抽象
public interface MainActivityView extends MvpView {
}
//具體實現
public class MainActivity extends BaseActivity implements MainActivityView {
private MainActivityPresenterApi presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
presenter = new MainActivityPresenter(this); //初始化Presenter
//下面調用方法我沒有固定,就是為了根據需求變化。當然大多數情況下是這樣的。
initData();
initView();
addListener();
}
@Override
protected void initData() {
}
@Override
protected void initView() {
}
@Override
protected void addListener() {
}
}
Model模塊
//抽象
public interface MainActivityModelApi {
}
//實現
public class MainActivityModel implements MainActivityModelApi {
}
Presenter模塊
//抽象
public interface MainActivityPresenterApi {
}
//實現
public class MainActivityPresenter implements MainActivityPresenterApi {
private MainActivityView view; //依賴的是抽象
private MainActivityModelApi model;
public MainActivityPresenter(MainActivityView view) {
this.view = view;
model = new MainActivityModel(); //創建Model真實對象
}
}
封裝工具類
工具類基本上都是提供一些靜態方法供外界調用的。
根據自己的需要來就行,我暫時封裝這么多,有需要再加,具體的到我的GitHub中看。下面我簡單介紹下他們的作用。
- AppUtils:主要用于獲取系統信息,控制一些通用的、應用級的操作;
- CrashHandler:處理未捕獲異常,參考我的這篇Android——Exception異常的正確打開方式;
- DisplayUtils:主要用于dp、sp、px等單位換算,獲取屏幕尺寸等;
- FileUtils:封裝文件IO操作,注意線程;
- GsonUtils:封裝Gson,避免頻繁創建Gson對象;
- ImageUtils:封裝Image操作;
- LogUtils:封裝Log,非常便捷高效的Log輸出,參考我的這篇Android——使用StackTraceElement實現自己的Log日志輸出管理類;
- MobileUtils:封裝部分設備信息獲取;
- NetworkUtils:封裝網絡信息獲取;
- ReflectUtils:幫助更高效的使用反射,參考我的這篇
Android——反射Reflect機制運用; - ThreadUtils:封裝Thread線程調度,參考我的這篇Android——線程管理之ExecutorService;
- ToastUtils:封裝Toast的使用,避免出現Toast錯亂的Bug。
工具類根據實際開發,可繼續不斷的擴展添加。