Android开发 - Presenter抽象类使用与管理视图显示与行为解析
Presenter是什么
-
职责:
-
Presenter 的主要职责是管理视图(通常是用户界面组件)的显示和行为
-
它不处理数据的逻辑,而是专注于如何展示数据
-
-
在 Leanback 库中的作用:
-
Leanback 库是为 Android TV 设计的一个库,提供了一些特殊的 UI 组件,比如 BrowseFragment。
-
Presenter 在 Leanback 库中用于定义每个项目(比如电影、电视节目等)在屏幕上的显示方式
-
-
类结构:
-
Presenter 是一个抽象类,你需要继承它并实现三个主要方法:
-
onCreateViewHolder(ViewGroup parent)
:创建并初始化视图组件,用于显示单个项目@Override public ViewHolder onCreateViewHolder(ViewGroup parent) { // 创建一个新的 ImageView 作为项目的视图 ImageView imageView = new ImageView(parent.getContext()); imageView.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT )); imageView.setPadding(10, 10, 10, 10); // 设置内边距 return new ViewHolder(imageView); // 返回 ViewHolder,包含这个 ImageView }
- 参数解析:
- parent:表示 RecyclerView 的父视图。你可以用它来获取上下文或创建视图的布局参数
- 参数解析:
-
onBindViewHolder(ViewHolder viewHolder, Object item)
:将数据绑定到视图,更新视图的内容以显示正确的数据@Override public void onBindViewHolder(ViewHolder viewHolder, Object item) { // 将数据对象转换为具体的类型(假设是 Movie 类) Movie movie = (Movie) item; // 获取 ViewHolder 中的视图组件(假设是 ImageView) ImageView imageView = (ImageView) viewHolder.view; // 设置 ImageView 的图像资源为电影海报 imageView.setImageResource(movie.getPosterResourceId()); }
- 参数解析:
- viewHolder:onCreateViewHolder 方法返回的 ViewHolder 对象,包含视图组件
- item:要绑定到视图的数据对象。你需要将其转换为具体的数据类型
- 参数解析:
-
onUnbindViewHolder(ViewHolder viewHolder)
:清理视图,以便回收资源@Override public void onUnbindViewHolder(ViewHolder viewHolder) { // 清理视图资源,这里不需要做任何操作 // 例如,如果是 ImageView,可以清除图像资源 ImageView imageView = (ImageView) viewHolder.view; imageView.setImageDrawable(null); // 清除图像资源 }
- 参数解析:
- viewHolder:包含视图组件的 ViewHolder 对象
- 参数解析:
-
-
代码示例
-
通过 MoviePresenter 类与 BrowseFragment 类示例解释:假设需要显示一系列电影海报
-
创建主布局文件:
res/layout/activity_main.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"> <!-- 容纳 BrowseFragment 的容器 --> <FrameLayout android:id="@+id/main_browse_fragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
-
创建一个自定义 Movie 类方便调用方法
//自定义数据模型类,用于封装电影信息 public class Movie { private final int posterResourceId; // 海报资源的 ID private final String title; // 电影标题 // 构造函数,用于创建 Movie 对象 public Movie(int posterResourceId, String title) { this.posterResourceId = posterResourceId; this.title = title; } // 获取海报资源 ID public int getPosterResourceId() { return posterResourceId; } // 获取电影标题 public String getTitle() { return title; } }
-
创建一个 MoviePresenter 类来定义每个电影海报的显示方式:
import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import androidx.leanback.widget.Presenter; //定义如何创建和绑定电影数据到视图 public class MoviePresenter extends Presenter { @Override //用于创建视图组件。在这个例子中,我们创建了一个 ImageView 作为电影海报的视图 //我们也可以创建一个包含多个视图(例如 ImageView 和 TextView)的复杂布局 public ViewHolder onCreateViewHolder(ViewGroup parent) { // 创建一个包含 ImageView 和 TextView 的布局 ImageView imageView = new ImageView(parent.getContext()); TextView textView = new TextView(parent.getContext()); // 设置布局参数和样式 imageView.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT )); textView.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT )); // 这里仅创建 ImageView 的 ViewHolder return new ViewHolder(imageView); } @Override //方法用于将数据绑定到视图。在这个例子中,我们将电影的海报图像设置到 ImageView 中 public void onBindViewHolder(ViewHolder viewHolder, Object item) { // 将电影海报数据绑定到 ImageView Movie movie = (Movie) item; // 假设 Movie 类包含电影信息 // 获取 ViewHolder 中的 ImageView 视图 ImageView imageView = (ImageView) viewHolder.view; //Movie 类假定包含电影的信息,如海报的资源 ID imageView.setImageResource(movie.getPosterResourceId()); // 设置电影海报图像 } @Override //方法用于清理视图资源。通常在视图不再需要显示时调用,这里可以进行资源释放等操作。在这个例子中,我们没有需要特别清理的资源。 public void onUnbindViewHolder(ViewHolder viewHolder) { // 清理视图资源,这里不需要做任何操作 } }
-
启动类中调用
import android.os.Bundle; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import androidx.leanback.app.BrowseFragment; import androidx.leanback.widget.ArrayObjectAdapter; import androidx.leanback.widget.ListRow; import androidx.leanback.widget.ListRowPresenter; import androidx.leanback.widget.HeaderItem; //初始化 BrowseFragment 并设置电影数据行 public class MainActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 设置布局文件,将 activity_main.xml 作为内容视图 setContentView(R.layout.activity_main); // 获取 FragmentManager,用于管理 Fragment FragmentManager fragmentManager = getSupportFragmentManager(); // 创建一个 BrowseFragment 实例 BrowseFragment browseFragment = new BrowseFragment(); // 使用 FragmentManager 将 BrowseFragment 添加到容器(main_browse_fragment)中 fragmentManager.beginTransaction() .replace(R.id.main_browse_fragment, browseFragment) .commit(); // 配置 BrowseFragment 的基本属性和数据行 browseFragment.setTitle("电影列表"); // 设置标题 setupRows(browseFragment); // 设置数据行 } // 配置 BrowseFragment 的数据行 private void setupRows(BrowseFragment browseFragment) { // 创建一个 ArrayObjectAdapter,并使用 ListRowPresenter 作为呈现器 ArrayObjectAdapter rowsAdapter = new ArrayObjectAdapter(new ListRowPresenter()); // 创建一个 HeaderItem,代表行的标题 HeaderItem headerItem = new HeaderItem(0, "热门电影"); // 创建一个 ArrayObjectAdapter,用于 ListRow 的数据 ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new MoviePresenter()); // 添加电影数据到适配器 listRowAdapter.add(new Movie(R.drawable.poster1, "电影 1")); listRowAdapter.add(new Movie(R.drawable.poster2, "电影 2")); // 将适配器添加到 ListRow,并添加到 rowsAdapter ListRow listRow = new ListRow(headerItem, listRowAdapter); rowsAdapter.add(listRow); // 设置适配器到 BrowseFragment browseFragment.setAdapter(rowsAdapter); } }
-
最后创建
AndroidManifest.xml
声明应用程序和启动 Activity就大功告成了
-