我在这里制作了一个问题的视频演示:https://www.youtube.com/watch?v=u9G4IVemayE
在视频中,我的recyclerview列表项中有一个复选框。 当用户选择将事件保存到数据库时,需要选中此复选框。但它将复选框设置为在列表项中进行检查,然后用户从他点击项目时所进入的活动中返回。
notifyDataSetChanged();而recyclerView.invalidate()也没有帮助,我在他的尝试中把它们放在了许多不同的地方。该复选框仅在我重新启动应用程序时更新。
EventActivity,其中显示列表项并从中保存:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_saveToDb:
DbHelper.getInstance(EventActivity.this).saveToDb(eventID, title, description, subtitle, start, end, 1, url, imgURL);
//1 in the parameters means that it shall have a checked box. 0:unchecked
MainActivity.databaseList.add(new Event(eventID, title, description, subtitle, start, end, url, imgURL, 1));
checkBox.setChecked(true);
//this checkbox is for an activity layout. nevermind it.
break;
}
}
这是在MainActivity中:
// I have tried to call this method different places.
public void initRecyclerView(List<Event> list) {
rvAdapter = new RvAdapter(list, this);
recyclerView.setAdapter(rvAdapter);
rvAdapter.notifyDataSetChanged();
}
**在RecyclerView Adapter类中,我设置了复选框,如果是1或0 **
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if(list.get(position).getIsDb() == 1){
holder.checkBox.setChecked(true);
}else{
holder.checkBox.setChecked(false);
}
}
整个MainActivity类:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
dbHelper = new DbHelper(this);
preferences = PreferenceManager.getDefaultSharedPreferences(this);
showListPref = preferences.getInt("SHOW_LIST", 3);
databaseList = new ArrayList<>();
jsonList = new ArrayList<>();
//Vi loader dataen fra start af, så de er klar til at vises frem når som helst og hurtigt
loadDatabaseData(this);
new JsonParser().execute();
toolbar = (Toolbar) findViewById(R.id.toolbar2);
toolbar.setTitleTextColor(Color.WHITE);
toolbar.showOverflowMenu();
setSupportActionBar(toolbar);
getSupportActionBar().setIcon(R.drawable.ic_location_city);
getSupportActionBar().setTitle(" Events in Aarhus");
/*
Sørger huske den valgte liste efter appen er lukket og vise den valgte igen når appen åbnes igen
og sætter også titlen på toolbaren efter hvilken database der vises.
*/
if (showListPref == 2) {
initRecyclerView(databaseList);
getSupportActionBar().setTitle(" Events in Aarhus (Database)");
} else if (showListPref == 3) {
initRecyclerView(jsonList);
getSupportActionBar().setTitle(" Events in Aarhus (JSON)");
}
}
/*
Her loader vi de data der er gemt i databasen og gemmer dem i List<Event> databaseList.
databaseList bruges til adapteren for recyclerviewet så dataen fra databasen kan vises i recyclerviwet.
*/
public void loadDatabaseData(Context context) {
dbHelper = new DbHelper(context);
sqLiteDatabase = dbHelper.getWritableDatabase();
Cursor c = sqLiteDatabase.rawQuery("SELECT * FROM " + DbHelper.DATABASE_NAME, null);
EventCurserWrapper wrapper = new EventCurserWrapper(c);
checkID = new ArrayList<>();
if (c.moveToFirst()) {
while (!c.isAfterLast()) {
databaseList.add(new Event(wrapper.getEvent().getEventID(), wrapper.getEvent().getTitle(), wrapper.getEvent().subtitle, wrapper.getEvent().getDescrption(), wrapper.getEvent().startTime, wrapper.getEvent().endTime, wrapper.getEvent().url, wrapper.getEvent().getImgURL(), wrapper.getEvent().isDb));
checkID.add(wrapper.getEvent().eventID);
c.moveToNext();
}
}
c.close();
}
/*
Denne metode bruger list parameteren til at skifte mellem de forskellige
lister når man fra menuen på toolbaren vælger om man vil se events fra JSON eller Databasen.
*/
public void initRecyclerView(List<Event> list) {
rvAdapter = new RvAdapter(list, this);
recyclerView.setAdapter(rvAdapter);
rvAdapter.notifyDataSetChanged();
}
/*
Async task bruges her til at loade json data og gemme dem i en arraylist
og køre asynkron med appens "mainthread".
*/
private class JsonParser extends AsyncTask<String, Void, String> {
HttpURLConnection conn;
URL url = null;
@Override
protected void onPreExecute() {
super.onPreExecute();
Toast.makeText(MainActivity.this, "LOADING DATA FROM API", Toast.LENGTH_LONG).show();
}
@Override
protected String doInBackground(String... params) {
try {
url = new URL(URL);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream inputStream = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
return (result.toString());
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (Exception ee) {
ee.printStackTrace();
}
return "";
}
@Override
protected void onPostExecute(String s) {
try {
JSONObject object = new JSONObject(s);
JSONArray events = object.getJSONArray("events");
for (int x = 0; x < events.length(); x++) {
JSONObject object1 = events.getJSONObject(x);
String eventID = object1.getString(EVENT_ID);
String title = object1.getString(TITLE);
String subtitle = object1.getString(SUBTITLE);
String description = object1.getString(DESCRIPTION);
String url = object1.getString(EVENT_URL);
String imgURL = object1.getString(PICTURE_URL);
JSONArray dateArray = object1.getJSONArray(DATES);
for (int y = 0; y < dateArray.length(); y++) {
JSONObject dateObject = dateArray.getJSONObject(y);
long start = dateObject.getLong(START);
long end = dateObject.getLong(END);
if (!title.isEmpty()) {
/*
Da datoen vi får fra JSON er i UNIX/Epoch format, så
konverter vi denne dato til rigtig "kalender" dato med koden nedunder
*/
Date date = new Date(start * 1000);
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.getDefault());
format.setTimeZone(TimeZone.getDefault());
String startdate = format.format(date);
Date date2 = new Date(end * 1000);
SimpleDateFormat format2 = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.getDefault());
format2.setTimeZone(TimeZone.getDefault());
String enddate = format2.format(date2);
/*
Her tjekker vi om de events der netop bliver loaded fra JSON om de i forvejen
eksister i databasen og hvis de gør, sættes flag til 1 og denne værdi bruges
i adapteren til at sætte checkboxen til true : 0 = false;
*/
int flag = 0;
if (DbHelper.getInstance(MainActivity.this).getEventIDs(eventID).contains(eventID) == true) {
flag = 1;
}
jsonList.add(new Event(eventID, title, subtitle, description, startdate, enddate, url, imgURL, flag));
}
}
}
rvAdapter.notifyDataSetChanged();
Toast.makeText(MainActivity.this, events.length() + " events loaded", Toast.LENGTH_LONG).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.listfragmentDemo:
startActivity(new Intent(MainActivity.this, MainActivityTest.class));
break;
case R.id.menu_showDatabase:
preferences.edit().putInt("SHOW_LIST", 2).apply();
initRecyclerView(databaseList);
getSupportActionBar().setTitle("Events in Aarhus (Database)");
break;
case R.id.menu_showJson:
preferences.edit().putInt("SHOW_LIST", 3).apply();
initRecyclerView(jsonList);
getSupportActionBar().setTitle("Events in Aarhus (JSON)");
break;
}
return super.onOptionsItemSelected(item);
}
/*
OnResume kaldes i stedet for onRestart, da vi kan være sikker på kaldes i activitens lifecyclus
som du engang fortalte på tavlen (;
*/
@Override
protected void onResume() {
super.onResume();
rvAdapter.notifyDataSetChanged();
}
}
RecyclerView的整个适配器类:
public class RvAdapter extends RecyclerView.Adapter<RvAdapter.ViewHolder> {
private static List<Event> list;
private static Context context;
public RvAdapter(List<Event> list, Context context) {
this.list = list;
this.context = context;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View v = inflater.inflate(R.layout.list_item, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.title.setText(list.get(position).getTitle());
holder.eventTime.setText("START: " + list.get(position).getStartTime() + " END: " + list.get(position).getEndTime());
/*
Hvis eventet eksisterer i databasen (1) så sæt checkboxen =true
*/
if(list.get(position).getIsDb() == 1){
holder.checkBox.setChecked(true);
}else{
holder.checkBox.setChecked(false);
}
}
@Override
public int getItemCount() {
return list.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView title, eventTime;
CheckBox checkBox;
public ViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.item_event_title);
eventTime = (TextView) itemView.findViewById(R.id.item_event_time);
checkBox = (CheckBox)itemView.findViewById(R.id.item_event_checkbox);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Intent intent = new Intent(context, EventActivity.class);
intent.putExtra("EVENT_ID", list.get(getAdapterPosition()).getEventID());
intent.putExtra("TITLE", list.get(getAdapterPosition()).getTitle());
intent.putExtra("START", list.get(getAdapterPosition()).getStartTime());
intent.putExtra("END", list.get(getAdapterPosition()).getEndTime());
intent.putExtra("DESCRIPTION", list.get(getAdapterPosition()).getDescrption());
intent.putExtra("SUBTITLE", list.get(getAdapterPosition()).getSubtitle());
intent.putExtra("URL", list.get(getAdapterPosition()).getUrl());
intent.putExtra("IMG_URL", list.get(getAdapterPosition()).getImgURL());
intent.putExtra("isDatabase", list.get(getAdapterPosition()).getIsDb());
intent.putExtra("POS", getAdapterPosition());
context.startActivity(intent);
}
}
}
答案 0 :(得分:1)
我在一行中找到了解决方案:MainActivity.jsonList.get(position).setIsDb(1)
;
我在EventActivity中使用intentExtras:position = getIntent().getIntExtra("POS", 0);
获取所单击项目的位置,其中在单击侦听项目后显示事件
并使用该位置更新模型数据的isDB变量。 然后onReturn to MainActivity我只需调用:notifyDataSetChanged();
我保存到数据库后,isDB变量在此处更新为1。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_saveToDb:
DbHelper.getInstance(EventActivity.this).saveToDb(eventID, title, description, subtitle, start, end, 1, url, imgURL);
MainActivity.databaseList.add(new Event(eventID, title, description, subtitle, start, end, url, imgURL, 1));
//Update isDB of the current model data for the seleceted list_item
MainActivity.jsonList.get(position).setIsDb(1);
//This is for another checkbox. nevermind it
checkBox.setChecked(true);
break;
}
}
答案 1 :(得分:0)
您正在更新db中的布尔值,但您的主要活动中的模型项目未更新,因为RecyclerView已经实例化。
有几种方法可以解决这个问题: