向用户显示list可以使用ListView或是GridView,在android5.0之前优先使用这些类,它们不关心具体的展示项,只负责展示项的滚动。
现在尽可能使用RecyclerView,因为它支持扩展。
RecyclerView顾名思义,就是回收再利用,循环往复
如果要显示TextView还需要其他两个类的支持,Adapter和ViewHolder。
ViewHolder很简单,只是contain视图。
Adapter是一个controller,从 model获取数据,然后提供给RecyclerView显示:
1、创建必要的ViewHolder
2、绑定ViewHolder至model
一个例子如下,使用内部类创建了ViewHolder和Adapter
public class CrimeListFragment extends Fragment {
private RecyclerView mCrimeRecyclerView;
private CrimeAdapter mAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.fragment_crime_list,container,false);
mCrimeRecyclerView = (RecyclerView)view
.findViewById(R.id.crime_recycler_view);
mCrimeRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
updateUI();
return view;
}
private void updateUI(){
CrimeLab crimeLab = CrimeLab.get(getActivity());
List<Crime> crimes = crimeLab.getCrimes();
mAdapter = new CrimeAdapter(crimes);
mCrimeRecyclerView.setAdapter(mAdapter);
}
private class CrimeHolder extends RecyclerView.ViewHolder
implements View.OnClickListener{
private TextView mTitleTextView;
private TextView mDateTextView;
private CheckBox mSolvedCheckBox;
private Crime mCrime;
public CrimeHolder(View itemView){
super(itemView);
itemView.setOnClickListener(this);
mTitleTextView = (TextView)itemView.findViewById(R.id.list_item_crime_title_text_view);
mDateTextView = (TextView)itemView.findViewById(R.id.list_item_crime_date_text_view);
mSolvedCheckBox = (CheckBox)itemView.findViewById(R.id.list_item_crime_solved_check_box);
}
public void bindCrime(Crime crime){
mCrime = crime;
mTitleTextView.setText(crime.getTitle());
mDateTextView.setText(crime.getCustomDateFormat());
mSolvedCheckBox.setChecked(crime.isSolved());
}
@Override
public void onClick(View v) {
Toast.makeText(getActivity(),
mCrime.getTitle() + " clicked!",Toast.LENGTH_SHORT)
.show();
}
}
private class CrimeAdapter extends RecyclerView.Adapter<CrimeHolder>{
private List<Crime> mCrimes;
public CrimeAdapter(List<Crime> crimes){
mCrimes = crimes;
}
@Override
public CrimeHolder onCreateViewHolder(ViewGroup parent,int viewType){
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View view = layoutInflater
.inflate(R.layout.list_item_crime,parent,false);
return new CrimeHolder(view);
}
@Override
public void onBindViewHolder(CrimeHolder holder,int position){
Crime crime = mCrimes.get(position);
holder.bindCrime(crime);
}
@Override
public int getItemCount(){
return mCrimes.size();
}
}
}
实现高效的RecyclerView刷新:
API 很简单:RecyclerView.Adapter.notifyItemChanged(int)
关键是如何确定position
假设一个情景:第一个activity是list,click其中任意一个就可以进入相应的activity,然后修改数据,再返回list时需要reload,单个刷新只需要。
解决方案1:使用startActivityForResult(intent,REQUEST_CODE);
启动另一个activity,
//父activity
//在适当的位置
startActivityForResult(intent,REQUEST_CODE);
...
public void onActivityResult(int requestCode,int resultCode,Intent data){
CrimeLab crimeLab = CrimeLab.get(getActivity());
List<Crime> crimes = crimeLab.getCrimes();
Crime crime;
UUID crimeId;
if(resultCode != Activity.RESULT_OK){
return;
}
//以下为关键代码
if(requestCode == REQUEST_CRIME){
if(data == null){
return;
}
crimeId = CrimeActivity.getClickCrimeId(data);
crime = crimeLab.getCrime(crimeId);
for(int i = crimes.size()-1;i>=0;i--){
if(crime.equals(crimes.get(i))){
mPositon = i;
}
}
}
//到此
}
...
...
在子activity中要返回给父activity信息,所以需要create Intent打包信息,只需要返回信息可以唯一确定该数据,在父activity中可以计算得到该position
...
private void setSomethingResult(type t){
Intent date = new Indent();
date.putExtra(TTTT,t);
setResult(RESULT_OK,data);
}
...