Android之AAC架構嘗試
阿新 • • 發佈:2019-01-08
一、AAC架構的前世今生
1、關於AAC需先了解一下Android Jetpack,Jetpack 是 Android 軟體元件的集合,使您可以更輕鬆地開發出色的 Android 應用。這些元件可幫助您遵循最佳做法、讓您擺脫編寫樣板程式碼的工作並簡化複雜任務,以便您可以專注於您關心的程式碼。Jetpack 包含與平臺 API 解除捆綁的 androidx.* 軟體包庫。這意味著,它提供向後相容性並且比 Android 平臺更頻繁地更新,從而確保您始終可以獲取最新且最好的 Jetpack 元件版本。
2、Android Jetpack的優勢
(1)元件是為協同工作而構建的,不過也可以單獨採用,同時利用 Kotlin 語言功能幫助您提高工作效率;
(2)Android Jetpack 可管理繁瑣的 Activity(如後臺任務、導航和生命週期管理),以便您可以專注於具體業務;
(3)Android Jetpack 元件圍繞現代化設計實踐構建而成,具有向後相容性,可以減少崩潰和記憶體洩漏。
3、Android Architecture Components(簡稱AAC),它是一套新的MVVM架構元件,使App的架構更加健壯,是Android Jetpack的架構元件具有可幫助管理介面元件生命週期、處理資料永續性等的類,以宣告方式將可觀察資料繫結到介面元素。
相關的API類:
二、程式碼實戰
1、定義model類(省略get 、set方法)
public class NewsDataVo {
private String id;
private String newsTitle;
private String newsContent;
private String newsUrl;
private int readNum;
}
2、定義ViewModel
public class NewsViewModel extends AndroidViewModel { private MutableLiveData<NewsDataVo> mData; private LiveData<NewsDataVo> switchDataMap; LiveData<NewsDataVo> getSwitchDataMap() { return switchDataMap; } public NewsViewModel(@NonNull Application application) { super(application); mData = new MutableLiveData<>(); switchDataMap = Transformations.switchMap(mData, new Function<NewsDataVo, LiveData<NewsDataVo>>() { @Override public LiveData<NewsDataVo> apply(NewsDataVo input) { MutableLiveData<NewsDataVo> temp = new MutableLiveData<>(); temp.setValue(input); return temp; } }); } /** * 模擬獲取網路資料 */ void httpGetData() { int len = 10; for (int i = 0; i < len; i++) { NewsDataVo dataVo = new NewsDataVo(); dataVo.setId("1223" + i); dataVo.setNewsTitle("Android AccArchitecture框架簡介" + i); dataVo.setNewsContent("Android Architecture Components,簡稱 AAC,一個處理UI的生命週期與資料的持久化的架構" + i); dataVo.setReadNum(i); mData.setValue(dataVo); } } }
3、定義LifecycleObserver管理View(Activity、Fragment)的生命週期
public class AccLifecycleObserver implements LifecycleObserver {
private Context context;
private String tag;
AccLifecycleObserver(Context context) {
this.context = context;
tag = context.getClass().getSimpleName();
}
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onCreate() {
Log.i(tag, "onCreate-----" + context.getClass());
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
Log.i(tag, "onStart-----" + context.getClass());
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
Log.i(tag, "onResume-----" + context.getClass());
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
Log.i(tag, "onPause-----" + context.getClass());
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop() {
Log.i(tag, "onStop-----" + context.getClass());
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy() {
Log.i(tag, "onDestroy-----" + context.getClass());
}
}
4、View層互動
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MainActivity mActivity;
private NewsViewModel newsViewModel;
private DataAdapter dataAdapter;
private List<NewsDataVo> mData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
addObserver();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.do_btn_tv:
newsViewModel.httpGetData();
break;
default:
break;
}
}
public void initView() {
mActivity = this;
mData = new ArrayList<>();
dataAdapter = new DataAdapter(mData);
findViewById(R.id.do_btn_tv).setOnClickListener(this);
RecyclerView recyclerView = findViewById(R.id.data_list_rv);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
recyclerView.setAdapter(dataAdapter);
}
private void addObserver() {
AccLifecycleObserver observer = new AccLifecycleObserver(mActivity);
getLifecycle().addObserver(observer);
ViewModelProvider.AndroidViewModelFactory instance = ViewModelProvider.AndroidViewModelFactory.getInstance(AccApp.sInstance);
newsViewModel = instance.create(NewsViewModel.class);
newsViewModel.getSwitchDataMap().observe(mActivity, new Observer<NewsDataVo>() {
@Override
public void onChanged(@Nullable NewsDataVo dataVo) {
assert dataVo != null;
mData.add(dataVo);
dataAdapter.notifyDataSetChanged();
}
});
}
class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewData> {
private List<NewsDataVo> mData;
DataAdapter(List<NewsDataVo> mData) {
this.mData = mData;
}
@NonNull
@Override
public ViewData onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
return new ViewData(LayoutInflater.from(mActivity).inflate(R.layout.news_item, viewGroup, false));
}
@Override
public void onBindViewHolder(@NonNull ViewData viewData, int i) {
NewsDataVo newsDataVo = mData.get(i);
viewData.numTv.setText(newsDataVo.getReadNum() + "人閱讀");
viewData.titleTv.setText(newsDataVo.getNewsTitle());
viewData.contentTv.setText(newsDataVo.getNewsContent());
}
@Override
public int getItemCount() {
return mData.size();
}
class ViewData extends RecyclerView.ViewHolder {
private ImageView imageView;
private TextView titleTv;
private TextView contentTv;
private TextView numTv;
public ViewData(@NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.image_iv);
titleTv = itemView.findViewById(R.id.title_tv);
contentTv = itemView.findViewById(R.id.content_tv);
numTv = itemView.findViewById(R.id.read_num_tv);
}
}
}
佈局xml檔案
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/do_btn_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginStart="20dp"
android:text="渲染資料"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v7.widget.RecyclerView
android:id="@+id/data_list_rv"
android:layout_marginTop="5dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/do_btn_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".MainActivity">
<ImageView
android:id="@+id/image_iv"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:scaleType="centerCrop"
android:src="@drawable/timg"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.constraint.Barrier
android:id="@+id/bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="image_iv"
app:layout_constraintStart_toEndOf="@id/image_iv" />
<TextView
android:id="@+id/read_num_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="right"
android:text="閱讀人數5人"
android:paddingStart="10dp"
android:paddingEnd="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/bar"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/title_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="標題"
android:paddingStart="10dp"
android:paddingEnd="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/bar"
app:layout_constraintTop_toBottomOf="@+id/read_num_tv" />
<TextView
android:id="@+id/content_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="內容"
android:paddingStart="10dp"
android:paddingEnd="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/bar"
app:layout_constraintTop_toBottomOf="@+id/title_tv" />
</android.support.constraint.ConstraintLayout>