-2

In MainActivity I have a RecyclerView list of CardView Items.

A click on any CardView launches a DetailsActivity CardView that show more data from the database, for that specific CardView.

A click on the DetailsActivity CardView launches EditActivity to edit that CardView's data. Clicking the "Save" button returns the user to the DetailsActivity so the user can see any edited changes to that CardView. The model for the CardView Item implements Parcelable so I use getParcelable() to pass the item and it's database data in the Activity Intents.

My problem is that after clicking "Save" the user returns to the DetailsActivity CardView and the old View for the CardView is shown (the View prior to the updated data the user just entered and saved to the database). I tried to use "adapter.notifyDataSetChanged()" to update the View, but no luck.

Somehow from the EditActivity, I need to re-load the MainActivity so the RecyclerView updates the Adapter and then return the user to the updated DetailsActivity CardView. Can I somehow use startActivityForResult()? What am I missing here?

Here is the UI progression:

MainActivity RecyclerView and Adapter:

--the Adapter uses a recyclerItemClickListener to send the clicked CardView Item back to the MainActivity so I can use onItemClick() to launch DetailsActivity.

--onItemClick() launches DetailsActivity via an Intent

DetailsActvity:

--uses an onClickListener and an Intent to launch EditActivity

EditActivity:

--I would like a click on the "Save" button to save the new/updated CardView data to the database and return the user back to the Details Activity so the user can see the changes to the CardView.

Adapter
...
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_contact_item, parent, false);
    final ItemHolder itemHolder = new ItemHolder(view);

        // Attach a Click listener to the items's (row) view.
        // itemView is from the ItemHolder().
        // onItemClick is the click method in MainActivity.
        itemHolder.itemView.setOnClickListener(new View.OnClickListener() {
            // Handles the row being clicked.
            @Override
            public void onClick(View view) {

                ListItem adapterItem = MyRecylerAdapter.this.getItem(itemHolder.getAdapterPosition()); 
                if (recyclerItemClickListener != null) {
                    // pass the item to the Main Activity
                    // through the RecyclerItemClickListener file and its
                    // public interface.
                    recyclerItemClickListener.onItemClick(itemHolder.itemView, adapterItem);
                }
            }
        });            
    return itemHolder;
}

MainActivity (the RecyclerView Activity)
...
@Override
public void onItemClick(View view, ListItem listItem) {

    Intent intent = new Intent(this, DetailsActivity.class);        
    intent.putExtra("item",listItem);
    startActivity(intent);
}

DetailsActivity
...
public class DetailsActivity extends AppCompatActivity {

    onCreate(...) {

        Bundle extras = getIntent().getExtras();
        if (extras != null) {            
            listItem = extras.getParcelable("item"); 
    }

    helper = new SQLiteDB(this);
    listItems = new ArrayList<>();
    listItems = helper.getAllDBItems();

    cvdcardType1 = (TextView) findViewById(R.id.cvdcardType1);
    if (listItems !=null && listItems.size() !=0) {
        cvdcardType1.setText(listItem.getType());
    }

    cardView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            Intent i = new Intent(DetailsActivity.this,EditActivity.class);
            i.putExtra("cvdItem",listItem);                
            startActivityForResult(i,REQUEST_CODE);

        }
    });
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Check which request we're responding to
    if (requestCode == REQUEST_CODE) {
        // Make sure the request was successful
        if (resultCode == RESULT_OK) {
            listItem = null;
            Bundle returnExtras = getIntent().getExtras();
            if (returnExtras != null) {
                listItem = returnExtras.getParcelable("returnItem");
                if (listItems !=null && listItems.size() !=0) {

                    cvdcardType1.setText(listItem.getType()); 
                    ...  
}
            }
        }
        else if (resultCode == Activity.RESULT_CANCELED) {
            // Finish the startActivityForResult().
            finish();
        }
    }
}

}

EditActivity

public class EditActivity extends AppCompatActivity {
onCreate(...) {
Bundle extras = getIntent().getExtras();
    if (extras != null) {            
        item = extras.getParcelable("cvdItem");
    }
}

// "Save Button"
public void onClickSaveEdits(View v) {
    // update database
    // update RecyclerView adapter and CardView Items
    // update DetailsActivity CardView
    // return the user to DetailsActivity to see updated CardView
    Intent returnIntent = new Intent(EditActivity.this, DetailsActivity.class);
    returnIntent.putExtra("returnItem", item);
    setResult(Activity.RESULT_OK,returnIntent);
    finish();
}
AJW
  • 1,578
  • 3
  • 36
  • 77
  • Why don't you finish DetailActivity while moving towards EditActivity and then start DetailActivity again in onBackPressed() method? – R.R.M Sep 05 '17 at 03:37
  • I will try that. – AJW Sep 05 '17 at 03:41
  • Ok. Try and let me know. – R.R.M Sep 05 '17 at 03:42
  • crash: Attempt to invoke virtual method ...on a null object. – AJW Sep 05 '17 at 03:43
  • I think because onCreate() in Details Activity is using the Item from getParcelable that comes from the MainActivity and then I try to start Details Activity from EditActivity which conflicts with getParcelable(). – AJW Sep 05 '17 at 03:45
  • Yes. You have to pass your cardview data of DetailActivity to EditActivity as well and then onBackPress() of EditActivity pass it back to DetailActivity. – R.R.M Sep 05 '17 at 03:49
  • I have also given answer to your question. Please refer that. – R.R.M Sep 05 '17 at 03:52
  • Ah, ok. But how do I pass back CardView Item from EditActivity back to DetailsActivity if onCreate() in DetailsActivity is already loading Item data from the getParcelable() that is from the MainActivity Intent? – AJW Sep 05 '17 at 03:52
  • I have given answer. Refer that. – R.R.M Sep 05 '17 at 03:53

2 Answers2

0

You have to finish DetailActivity while moving towards EditActivity and then start DetailActivity again in onBackPressed() method like below:

Intent intent = new Intent(EditActivity.this, DetailsActivity.class);        
intent.putExtra("item",item);
startActivity(intent);
R.R.M
  • 780
  • 4
  • 10
  • same result, crash due to null object. MainActivity is passing the Item via an Intent which is then loaded in DetailsActivity with getParcelable(). And now DetailsActivity is getting an Item via the new "intent" from the EditActivity and that conflicts with the MainActivity Item. – AJW Sep 05 '17 at 03:57
  • But it should not. Even you are checking null condition. Can you post your DetailActivty and EditActivity code? – R.R.M Sep 05 '17 at 04:01
  • Ok I will add above. – AJW Sep 05 '17 at 04:03
  • Added the relevant sections for DetailsActivity and EditActivity. – AJW Sep 05 '17 at 04:14
  • You have given wrong name of DetailsActivity. Did you noticed that? – R.R.M Sep 05 '17 at 04:46
  • My bad. I copied from an earlier version. Edited and corrected above. – AJW Sep 05 '17 at 04:48
  • Can you print log for item before returnIntent.putExtra("item", item); this line in onClickSaveEdits of EditActivity. Also add finish() after startActivity(returnIntent); this line in same method. – R.R.M Sep 05 '17 at 04:54
  • Android newbie here. how do I print log? Use log.d("item")? – AJW Sep 05 '17 at 04:55
  • Log.e("item",""+item); – R.R.M Sep 05 '17 at 04:56
  • Ok I added finish(); after startActivity(). I am using Android Studio. How do I get Log results? In Android Monitor? – AJW Sep 05 '17 at 05:01
  • in logcat, selections are "Verbose" and "Show only selected application" but I do not see any red or any "item". Do I need to filter on the word "item" or something else? – AJW Sep 05 '17 at 05:05
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/153651/discussion-between-r-r-m-and-ajw). – R.R.M Sep 05 '17 at 05:09
0

Simply you can read database items in onResume() in MainActivity again after editing detail.

allList = sqLiteDB.getAllDBItems();
adapter.notifyDatasetChanged();

In simple words read list again from database and re draw it. And make sure you saved the change in database in EditActivity

and call your EditActivity with startActivityForResult() whatever you change pass it back in setResult();

and in onActivityResult method of DetailActivity populate data with new values.

Zar E Ahmer
  • 33,936
  • 20
  • 234
  • 300
  • Ah, I think that's exactly what I need. I will give it a go and report back...Android newbie here, I should have studied the Activity lifecycle chart much more. – AJW Sep 27 '17 at 15:58
  • No luck. The single CardView in the DetailActivity View is not being refreshed by "adapter.notifyDataSetChanged()". Only the View for the MainActivity RecyclerView full list of CardView items is refreshed once I finish()' the DetailActivity. Any thoughts on how to fix? – AJW Sep 27 '17 at 23:47
  • See the edits above: I changed setOnClickListener to use startActivityForResult(). I used a putExtra in the EditActivity to return the ListItem item back to the DetailActivity. I added the onActivityResult() in the DetailActivity and I added adapter code in the onResume(). App is crashing saying "Attempt to invoke method String ListItem.getType() on a null object reference." How can it be null if I am returning the item from EditActivity using getParcelable("returnItem")? – AJW Sep 28 '17 at 00:26
  • adapter is used by RecyclerView why have you put notifyDatasetChanged code in DetailActivity. It only handles onActivityResult() . study how to return result to previous activity in onActivityResult. And update your latest code in your question. May be I find the mistake – Zar E Ahmer Sep 28 '17 at 06:10
  • There is no problem updating the RecyclerView when the user returns to it later. My issue is I update the data for the CardView shown in Detail Activity and when the data is saved in EditActivity I want the user to return to the Detail Activity and see that the data has been updated. The View in Detail Activity is not updating. – AJW Sep 28 '17 at 12:39
  • on save button in EditActivity setResult like https://stackoverflow.com/a/10407371/3496570 and in onActivityResult of DetailActivity update it – Zar E Ahmer Sep 29 '17 at 06:20
  • I did. See the edited code above. For setResult() I used "returnIntent.putExtra("returnItem", item);" For onActicityResult in DetailActivity I used "listItem = returnExtras.getParcelable("returnItem");" to get returnItem. And then I get null object crash when trying to setText. – AJW Sep 29 '17 at 14:17
  • debug onClickSaveEdits item value before passing it back to DetailActivity. May be it's null. And make sure getType() is parcelable . Check have your added it to parcelable methods – Zar E Ahmer Oct 02 '17 at 05:09