当我的RecyclerView应该

时间:2016-05-27 09:15:15

标签: android

我在这里制作了一个问题的视频演示: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);



    }
}

}

2 个答案:

答案 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已经实例化。

有几种方法可以解决这个问题:

  • 在MainActivity onResume方法中重新加载RecyclerView数据模型。
  • 从EventActivity向MainActivity通知RecyclerView中的更改和更新项目(类LocalBroadcast管理器可以帮助您)(最佳方法
  • 始终从db读取以获取更新的bool值(在方法中 - &gt; list.get(位置)。 getIsDb())(最糟糕的方法