delete item from Activity after receive it in Fragment / Lifecycle issue - android

I need some help. I've got activity where I create item. Next I want to send it to the fragment in second activity so I need to firstly send it to that Activity (am I correct ?). This is how I create item :
public void savePart() {
Part part = new Part(name,quantity,"","",tag,"","2");
Intent intent = new Intent(this,InvActivity.class);
intent.putExtra("Part", (Serializable) part);
setResult(2,intent);
finish();
}
This is how I receive it in second activity:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == 2) {
part = (Part) data.getSerializableExtra("Part");
}
}
I've got method to return the part in fragment :
public Part getMyData() {
return part;
}
In Fragment's onResume() I receive the Part object, check if object with similar code exists and add it to the ListView if not:
#Override
public void onResume() {
super.onResume();
List<Part>subList = new ArrayList<>();
if (mActivity.getMyData() != null) {
Part part = mActivity.getMyData();
for(Part parts : mParts) {
if (parts.getCode().contains(part.getCode())) {
subList.add(parts);
}
}
if (subList.size() == 0) {
mParts.add(part);
adapter = new PartAdapter(getContext(), R.layout.part_item, mParts, mActivity, new AdapterCallback() {
#Override
public void onMethodCallback() {
}
});
mPartsLV.setAdapter(adapter);
} else {
Toast.makeText(getContext(), R.string.equipment_exists, Toast.LENGTH_SHORT).show();
}
}
}
So far everything works well. items are added correctly and shown in ListVIew in fragment.Here is where the problem begins :) In listView row I've got imageView which deletes item from ListView.
mDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mParts.remove(part);
notifyDataSetChanged();
}
});
That works great to but ... when fragment comes back to onResume() deleted item shows again is ListView. That is because each time I receive Part and check if exists in List. I think I should somehow clear intent after receiving Part from Activity where Part was created but I don't know how ? Maybe any other solution,please ?

Declare your subList as public and populate it once. So you need to modify your onResume function a bit. Check if the list is populated already. If not, populate the list from the extras and vice versa.

ListsubList = new ArrayList<>();
your list is created every time when onResume() called that's why delete entries could not managed. So either take a copy of this list or every time check which elements got deleted,and then set data to listview.

Related

Correct way to refresh a ListView adapter in Android

I have a list of items. I have a button that sends you to another activity in order to create a new item. When the new item is saved an intent sends you back to the activity with the list where the new item should be added. The adapter extends from BaseAdapter without filtering, it just sets the data to the views.
My code is this:
onCreate(){
ListView listView = findItemById......
listView.setListeners.......
}
onResume(){
data = getData();
adapter = new ListAdapter(context,data);
listView.setAdapter(adapter);
}
It works but is this correct?
Can I use creation of adapter and setAdapter in onCreate and use notifyDataSetChanged() only in onResume somehow?
I think the correct way to do it is a use
startActivityForResult(...)
method to launch your Second activity (where your new items is added).
And in your second activity use
setResults(RESULT_OK or RESULT_CANCELLED)
(diffrent result when new items is added or user just back to prev screen).
Then in your ListAdapter class add method
public void updateData(List data) {
this.data = new ArrayList<>(data);
notifyDataSetChanged();
}
And call it in your onActivityResults(...)
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == YOUR_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
adapter.updateData(...your data from result Intent, or from anywhere else...);
}
}
Also i strongly recommend you to use RecyclerView instead of ListView
UPD: to answer your question - i think that biggest mistake in your code, is to create new instance of ListAdapter object in onResume() method, when it's not necessary
Add this method to your adapter and then call it with new data using adapter.udpateData(data):
public void updateData(List data) {
this.data = data;
notifyDataSetChanged();
}
Also, you can use notifyItemRangeInserted(0, data.size())
Hi OnActivityResult read all data create the new object and add to the list and call notifyDatasetChanged() , i will automatically refresh ui

Updating list in one class after action in another

I have a problem where by I have two activities, activity 1 and activity 2. Activity 1 contains a listview of contents in my SQLite database, activity 2 contains a button that when pressed preforms a query on the database. This query when run will alter the information in activity 1's list.
When I press the button the query works fine but the listview in activity 1 does not get updated. I know I have to use notifyDataSetChanged on the listview in order to have the list information updated.
My problem is how do I call this method on the list in activity 1 from the button listener in activity 2?
Listview and adapter in activity 1
String[] columns = new String[] {adapter.KEY_CONTENTS_NAME, adapter.KEY_CONTENTS_MEASUREMENT, adapter.KEY_CONTENTS_UNIT};
int[] to = new int[] {R.id.ingredientName, R.id.ingredientMeasurement, R.id.ingredientUnit};
SimpleCursorAdapter myCursorAdapter = new SimpleCursorAdapter(this,R.layout.row2, cursor, columns, to, 0);
ListView ingredientList = (ListView) findViewById(R.id.ingredientList);
ingredientList.setAdapter(myCursorAdapter);
Button in activity 2
Button cookButton = (Button) findViewById(R.id.cookButton);
cookButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//simple SQL query
//call to activity 2 to update the list
}
});
You can use startActivityForResult to achieve this.
In your first activity when you want to start the second activity like this using startActivityForResult.
Intent myIntent = new Intent(FirstActivity.this, SecondActivity.class);
int FIRST_ACTIVITY_CODE = 100
startActivityForResult(intent, FIRST_ACTIVITY_CODE);
In your second activity when doing the click you want to setResult okay and then quit the activity to return to the first activity.
Button cookButton = (Button) findViewById(R.id.cookButton);
cookButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//simple SQL query
setResult(RESULT_OK);
finish();
}
});
In your first activity you have to override onActivityResult and then update your list.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FIRST_ACTIVITY_CODE) {
myCursorAdapter.notifyDataSetChanged();
}
}
So you can communicate with activities by using onActivityResult. If you want to pass the data you got back from your SQL query in the second activity to your first activity you can use setResult(int resultCode, Intent data)
Then write this function in your list activity:
#onResume
public void onResume(){
super.onResume();
myCursorAdapter.notifyDataSetChanged();
}
As you go back to that activity, this function will be called and you can notify about the changes here by calling notifyDataSetChanged.
You could start activity using startActivityForResult. Here is the documentation and an example: http://developer.android.com/training/basics/intents/result.html
On the first activity you should have something like this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SECOND_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// load data from db
// add data to the list view (create a new adapter or clear the items from the old one and add the new items)
// notifyDataSetChanged on adapter
}
}
}
Before calling notifyDataSetChanged. Load again info from db (and check if it was updated) and add it to the list view. Then call notifyDataSetChanged

Update data in local SQLite then return to parent Activity solution

I am learning Android. I am creating an application that have 2 activities: List Activity list all records from a local SQLite and Edit activity will create/update record.
On Edit activity, I have a button. When the button clicked, I will process creating/updating the record then returning back to parent activity (List activity).
On Button click. I have 2 solutions to process Create/Update:
1. Process Create/Update in UI thread ( Not using AsyncTask )
This solution is fine but I may have to show 'Processing' dialog.
2. Use AsyncTask -- so creating/updating happens in background Thread. Here is my code in Edit Activity:
---- NOTE that Edit activity use Fragment so getActivity() method will return the instance of EditActivity
saveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AsyncTask<Phrase, Integer, Integer> asyncTask = new AsyncTask<Phrase, Integer, Integer>() {
#Override
protected Integer doInBackground(Phrase... params) {
Phrase phrase = params[0];
if (phrase._id > 0) {
PhraseDao.update(DbManager.openWrite(getActivity()), phrase);
} else {
PhraseDao.insert(DbManager.openWrite(getActivity()), phrase);
}
return null;
}
#Override
protected void onPostExecute(Integer result) {
Intent intent = new Intent();
getActivity().setResult(Activity.RESULT_OK, intent);
// Close Edit Activity then Go back to List activity
getActivity().finish();
// MY QUESTION: What happens if the EditActivity (getActivity) already destroyed?
// How can I handle destroyed activity here
}
};
asyncTask.execute(a_phrase);
}
});
I don't know how to handle 'onPostExecute' method in the case Edit Activity ( accessed by getActivity()) Already destroyed.
Anyone have any ideas? Thank you!
Add a null check to see if activity exists i.e
if(getActivity() != null){
Intent intent = new Intent();
getActivity().setResult(Activity.RESULT_OK, intent);
getActivity().finish();
}

Coming back from intent, do something

I have an android application which is using listView. After clicking on any item on the list it shows you AlertDialog where you can chose either edit or delete. After clicking edit it starts a new intent sending some extra strings to fill up the form for editing. I would like to refresh the list after I click on button save in that EditActivity.
I have read about notifyDataSetChanged() and I think it could work I just would like to know if there is any method which is in MainClass (listView class) and it is executed right after I came back from intent, right after clicking save button in EditActivity.
Or may I just add notifyDataSetChanged() method after I start an activity in the MainActivity?
public class yourClass extends ListActivity {
//define a class variable here.
private ArrayAdapter<Friend> adapter;
#Override
public void onCreate(Bundle savedInstanceState){
//Change this line setListAdapter(new ArrayAdapter<Friend>(this, android.R.layout.simple_list_item_1, db.getAllFriends()));
to
adapter = new ArrayAdapter<Friend>(this, android.R.layout.simple_list_item_1, db.getAllFriends());
setListAdapter(adapter);
}
#Override
public void onResume(){
super.onResume();
adapter.notifyDataSetChanged();
}
}
You can add listView.notifyDataSetChanged() in your activity onResume() function.
#Override
public void onResume(){
super.onResume();
yourListView.notifyDataSetChanged();
}
Use the method startActivityForResult() when opening your EditActivity then implement onActivityResult method in your main class. There you will be able to use notifyDataSetChanged
Read this from the doc
use startActivityForResult to call your EditActivity (this isn't simplest way to do what you want but is good way to do), by using this you can find out what is the result of your edit
Intent i = new Intent(this, EditActivity.class);
startActivityForResult(i, 1);
In your EActivity set the data which you want to return back to MainActivity
Intent returnIntent = new Intent();
returnIntent.putExtra("result",YOUR_RESULT); // skip if you do not want to return special result
setResult(RESULT_OK,returnIntent);
finish();
if you want to send cancel action (in your case fail edit) use this
Intent returnIntent = new Intent();
setResult(RESULT_CANCELED, returnIntent);
finish();
Now in your MainActivity class write following code for onActivityResult() method
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if(resultCode == RESULT_OK){
String result=data.getStringExtra("result"); // result sent from EditActivity
listViewAdapter. notifyDataSetChanged();
}
if (resultCode == RESULT_CANCELED) {
//Write your code if there's no result
}
}
}//onActivityResult

Android Activity onResume() and onActivityResult() conflict

Have a problem. In my main Activity I have a ListView. And I need to refresh it any time I returned to this Activity. I use onResume() method for this:
#Override
protected void onResume() {
super.onResume();
refreshCategoriesList();
}
private void refreshCategoriesList() {
// ...
categoriesListAdapter = new CategoryListItemAdapter(
this, R.layout.category_item,
categories
);
categoriesListView.setAdapter(categoriesListAdapter);
}
As you can see I use refreshing adapter extended from ArrayAdapter for changing data in ListView.
But in some cases I need scroll this list to the end, for ex. when I add new item to it. And I use onActivityResult(...) method for this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// ...
refreshCategoriesList();
categoriesListView.setSelection(categoriesListAdapter.getCount() - 1);
}
But I have one problem. When I add new item to my list both this methods executed in order onActivityResult(...) and after that onResume(). And I have:
List data refreshed to times with refreshCategoriesList() (But it's not main problem);
After executing of onResume() scrolled to end list restored to first item position :( It's a problem. Because when I add new item I want scroll list to the end.
How can I resolve this problem. Can I in some cases call only onActivityResult(...) method (when I need to scroll list) and in other onResume() method (when I simply want to refresh list data)?
You can use notifyDataSetChanged() method from ArrayAdapter instead of recreating adapter every time.
private void refreshCategoriesList() {
categoriesListAdapter.notifyDataSetChanged();
}

Categories

Resources