这是实现这组功能的一种方法。原始问题中描述的所有功能都已实现并可在此处获得:Sample Application on GitHub。另外,如果您有改进建议,请在此处或在 GitHub 上提出建议。
通常,列表活动中有一个模型,该模型作为额外的传递到幻灯片活动中。幻灯片活动模型的更改很容易在数据库中反映,并且需要一些努力才能在用户按下后退按钮时让幻灯片活动的更改出现在列表活动中。
主要活动onCreate 创建一个 SQLite 数据库适配器并将一些数据放入其中。它创建一个ArrayList<Model> 并使用它来构建RecyclerView.Adapter:
public class RecyclerSqlListActivity extends AppCompatActivity {
....
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_list);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView1);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
try {
repository = new DbSqlliteAdapter(this);
repository.open();
//repository.deleteAll();
//repository.insertSome();
modelList = repository.loadModelFromDatabase();// <<< This is select * from table into the modelList
Log.v(TAG, "The modelList has " + modelList.size() + " entries.");
recyclerViewAdapter = new MyRecyclerViewAdapter(this, modelList);
recyclerView.setAdapter(recyclerViewAdapter);
recyclerView.hasFixedSize();
} catch (Exception e) {
Log.v(TAG, "Exception in onCreate " + e.getMessage());
}
}
...
}
这是布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
</LinearLayout>
RecyclerView.Adapter 是听众所在的位置。我听一下点击和长按。单击启动幻灯片活动,长按更改数据库,以便图标显示或不显示。当用户采取更改数据的操作时,我需要确保模型和数据库得到更新,并且我需要通知视图发生了某些变化。请注意,此实现仅管理实际更改的内容,而不是刷新所有内容。
class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
static class ViewHolder extends RecyclerView.ViewHolder {
ImageView iconImageView;
TextView nameTextView;
TextView secondLineTextView;
TextView dbItemTextView;
TextView hiddenTextView;
TextView descriptionTextView;
ViewHolder(View itemView) {
super(itemView);
iconImageView = (ImageView) itemView.findViewById(R.id.bIcon);
nameTextView = (TextView) itemView.findViewById(R.id.bName);
secondLineTextView = (TextView) itemView.findViewById(R.id.bSecondLine);
dbItemTextView = (TextView) itemView.findViewById(R.id.bDbItem);
hiddenTextView = (TextView) itemView.findViewById(R.id.bHidden);
descriptionTextView = (TextView) itemView.findViewById(R.id.bDescription);
}
}
private List<Model> mModelList;
private Context mContext;
MyRecyclerViewAdapter(Context context, List<Model> modelList) {
mContext = context;
mModelList = new ArrayList<>(modelList);
}
@Override
public MyRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View modelView = inflater.inflate(R.layout.list_item, parent, false);
return new ViewHolder(modelView);
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
final Model model = mModelList.get(position);
viewHolder.nameTextView.setText(model.getName());
viewHolder.secondLineTextView.setText(model.getSecond_line());
viewHolder.dbItemTextView.setText(model.getId() + "");
viewHolder.hiddenTextView.setText(model.getHidden());
viewHolder.descriptionTextView.setText(model.getDescription());
if ("F".equals(model.getHidden())) {
viewHolder.secondLineTextView.setVisibility(View.VISIBLE);
viewHolder.iconImageView.setVisibility(View.INVISIBLE);
} else {
viewHolder.secondLineTextView.setVisibility(View.INVISIBLE);
viewHolder.iconImageView.setVisibility(View.VISIBLE);
}
// DEFINE ACTIVITY THAT HAPPENS WHEN ITEM IS CLICKED
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.v(TAG, "setOnClickListener fired with view " + view); // view is RelativeLayout from list_item.xml
int position = mModelList.indexOf(model);
Log.v(TAG, "position was : " + position);
Intent intent = new Intent(mContext, DetailSlideActivity.class);
intent.putExtra(DetailSlideActivity.EXTRA_LIST_MODEL, (Serializable)mModelList);
intent.putExtra(DetailSlideActivity.EXTRA_POSITION, position);
((Activity)mContext).startActivityForResult(intent, RecyclerSqlListActivity.DETAIL_REQUEST);
}
});
// If the item is long-clicked, we want to change the icon in the model and in the database
viewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
Log.v(TAG, "setOnLongClickListener fired with view " + view); // view is RelativeLayout from list_item.xml
Log.v(TAG, "setOnLongClickListener getTag method gave us position: " + view.getTag());
int position = mModelList.indexOf(model);
Log.v(TAG, "position was : " + position);
String hidden = model.getHidden();
Log.v(TAG, "hidden string was : " + hidden);
if ("F".equals(hidden)) {
model.setHidden("T");
DbSqlliteAdapter.update(model);
view.findViewById(R.id.bIcon).setVisibility(View.INVISIBLE);
} else {
model.setHidden("F");
view.findViewById(R.id.bIcon).setVisibility(View.VISIBLE);
}
Log.v(TAG, "updating the database");
DbSqlliteAdapter.update(model);
Log.v(TAG, "notifyItemChanged being called");
notifyItemChanged(position);
boolean longClickConsumed = true; // no more will happen :)
return longClickConsumed;
}
});
}
我不会把所有代码都放在这里,我只放一个子集,更多细节可以通过上面的 github 链接找到。但最后一条评论是关于该应用程序如何设计以获取在幻灯片活动期间更改的项目列表。每次幻灯片活动发生更改时,位置都会在数据库更新的同时保存。然后,当幻灯片活动结束时,onActivityResult() 拉出所有这些位置并更新了原始活动中保存的模型。
public class RecyclerSqlListActivity extends AppCompatActivity {
....
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if(requestCode == RecyclerSqlListActivity.DETAIL_REQUEST){
Log.v(TAG, "onActivityResult fired <<<<<<<<<< resultCode:" + resultCode);
//String[] changedItems = intent.getStringArrayExtra(RecyclerSqlListActivity.DETAIL_RESULTS); // We could return things we learned, such as which items were altered. Or we could just update everything
//modelList = repository.loadModelFromDatabase();// <<< This is select * from table into the modelList
Integer[] changedPositions = DbSqlliteAdapter.getChangedPositions();
for (Integer changedPosition : changedPositions) {
Model aModel = modelList.get(changedPosition);
DbSqlliteAdapter.loadModel(aModel);
recyclerViewAdapter.notifyItemChanged(changedPosition);
}
}
}
....
}
以下是一些与数据库交互的类。我决定反对ContentProvider,因为根据文档,这是为了在应用程序之间而不是在一个应用程序内共享数据。
class DbSqlliteAdapter {
....
static Model loadModel(Model model) {
Model dbModel = DbSqlliteAdapter.getById(model.getId() + "");
Log.v(TAG, "looked up " + model.getId() + " and it found " + dbModel.toString());
model.setId(dbModel.getId());
model.setName(dbModel.getName());
model.setSecond_line(dbModel.getSecond_line());
model.setDescription(dbModel.getDescription());
model.setHidden(dbModel.getHidden());
return model;
}
private static class DatabaseHelper extends SQLiteOpenHelper {....}
....
static void update(Model model) {
ContentValues values = fillModelValues(model);
Log.v(TAG, "Working on model that looks like this: " + model);
Log.v(TAG, "Updating record " + values.get(Model.ID) + " in the database.");
mDb.update(SQLITE_TABLE, values, Model.ID + "=?", new String[] {"" + values.get(Model.ID)});
Model resultInDb = getById("" + values.get(Model.ID));
Log.v(TAG, "after update, resultInDb: " + resultInDb);
}
static void update(Model model, int position) {
positionSet.add(position);
update(model);
}
static Integer[] getChangedPositions() {
Integer[] positions = positionSet.toArray(new Integer[0]);
positionSet.clear();
return positions;
}
....
}