一、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>