继续积累吧。
RecyclerView
RecyclerView
是什么?
我们已经使用过一些View来构建我们的App,例如ScrollView
,ListView
等。当时RecyclerView
的应用场景是在于它能够对数据进行缓存,从而不需要直接将所有的数据加载到内存中。例如我们的应用中需要使用大量的图片列表,如果将所有的图片直接放到内存中,会导致应用的速度变慢,同时浪费内存。
所以我们使用RecyclerView
来优化数据的展示。RecyclerView
的主要模式是RecyclerView+Adapter+ViewHolder
。
RecyclerView
-
RecyclerView
需要放置在layout
文件中,并分配相应的资源id
:
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview_forecast"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
-
RecyclerView
需要使用不同的LayoutManager
来完成不同的布局分布。RecyclerView
通过setLayoutManager
函数来设定指定的LayoutManager。RecyclerView
可以使用setAdapter
方法,设置指定的Adapter。
/*
* LinearLayoutManager can support HORIZONTAL or VERTICAL orientations. The reverse layout
* parameter is useful mostly for HORIZONTAL layouts that should reverse for right to left
* languages.
*/
LinearLayoutManager layoutManager
= new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(layoutManager);
/*
* Use this setting to improve performance if you know that changes in content do not
* change the child layout size in the RecyclerView
*/
mRecyclerView.setHasFixedSize(true);
// TODO (11) Pass in 'this' as the ForecastAdapterOnClickHandler
/*
* The ForecastAdapter is responsible for linking our weather data with the Views that
* will end up displaying our weather data.
*/
mForecastAdapter = new ForecastAdapter(this);
/* Setting the adapter attaches it to the RecyclerView in our layout. */
mRecyclerView.setAdapter(mForecastAdapter);
Adapter
- 当
RecyclerView
需要加载一个数据项的时候,调用函数onCreateViewHolder
,从Adapter
中获取一个ViewHolder
。每当RecyclerView
需要获得更多的ViewHolder
的时候,会不断从Adapter
中获得。但是,ViewHolder
并不是无限的创建,而是创建有限个ViewHolder
之后,重复利用之前的ViewHolder
,并不断更新旧的ViewHolder
中的数据来刷新页面。
在onCreateViewHolder
方法中,需要将一个item项对应的layout资源进行填充到ViewHolder中。使用函数LayoutInflater.inflate(,,false)
,最后一个参数需要注意,虽然不知道为什么需要用false
,但是这个是必须的,否则就会报错。
/**
* This gets called when each new ViewHolder is created. This happens when the RecyclerView
* is laid out. Enough ViewHolders will be created to fill the screen and allow for scrolling.
*
* @param viewGroup The ViewGroup that these ViewHolders are contained within.
* @param viewType If your RecyclerView has more than one type of item (which ours doesn't) you
* can use this viewType integer to provide a different layout. See
* {@link android.support.v7.widget.RecyclerView.Adapter#getItemViewType(int)}
* for more details.
* @return A new ForecastAdapterViewHolder that holds the View for each list item
*/
@Override
public ForecastAdapterViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
Context context = viewGroup.getContext();
int layoutIdForListItem = R.layout.forecast_list_item;
LayoutInflater inflater = LayoutInflater.from(context);
boolean shouldAttachToParentImmediately = false;
View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
return new ForecastAdapterViewHolder(view);
}
- 当
RecyclerView
需要向ViewHolder
中放置数据的时候,需要调用Adapter
的函数onBindViewHolder
,函数使用当前的position
,获取对应的位置,并绑定数据。
/**
* OnBindViewHolder is called by the RecyclerView to display the data at the specified
* position. In this method, we update the contents of the ViewHolder to display the weather
* details for this particular position, using the "position" argument that is conveniently
* passed into us.
*
* @param forecastAdapterViewHolder The ViewHolder which should be updated to represent the
* contents of the item at the given position in the data set.
* @param position The position of the item within the adapter's data set.
*/
@Override
public void onBindViewHolder(ForecastAdapterViewHolder forecastAdapterViewHolder, int position) {
String weatherForThisDay = mWeatherData[position];
forecastAdapterViewHolder.mWeatherTextView.setText(weatherForThisDay);
}
- 这个方法是最简单的一个方法,直接返回
Adapter
中所有的数据量。
/**
* This method simply returns the number of items to display. It is used behind the scenes
* to help layout our Views and for animations.
*
* @return The number of items available in our forecast
*/
@Override
public int getItemCount() {
if (null == mWeatherData) return 0;
return mWeatherData.length;
}
ViewHolder
- 真正实现数据的绑定,对一个RecyclerView中的一个数据项,需要使用ViewHolder来进行保存,更新和展示。
- 同时ViewHolder也可以处理Click事件,需要实现
RecyclerView.OnClickListener
接口,并在构造函数内完成ClickListener
的绑定(使用函数setOnClickListener
)。
在onClick
函数(类似于回调函数)中,使用getAdapterPosition
函数中,可以得到当前数据在Adapter中,对应的位置,使用这个位置信息,确定所要修改和更新的数据。
“`
/**
* Cache of the children views for a forecast list item.
*/
public class ForecastAdapterViewHolder extends RecyclerView.ViewHolder
implements RecyclerView.OnClickListener{
public final TextView mWeatherTextView;public ForecastAdapterViewHolder(View view) {
super(view);
mWeatherTextView = (TextView) view.findViewById(R.id.tv_weather_data);
// TODO (7) Call setOnClickListener on the view passed into the constructor (use 'this' as the OnClickListener)
view.setOnClickListener(this);
}
@Override
public void onClick(View view) {
int index = getAdapterPosition();
mClickHandler.onClick(mWeatherData[index]);
}
// TODO (6) Override onClick, passing the clicked day's data to mClickHandler via its onClick method
}“`1