fragment does not reflect changes - android

I am trying to create an application in which my Fragment contains one listview which is populated from a database, and when one of the item is clicked, a new activity starts.
In this new activity, I update the database, and then come back to the first Fragment (by pressing back button).
What happens next is that the ListView in the first Fragment does not take the changes I made in the second Activity into account.
And strange thing is that when I start the application again, the Fragment shows the updated list.
How can I automatically update the ListView when making changes to the database?

Try to use the onResume( ) method in your Fragment, so you can told the Adapter that the Dataset has changed.
#Override
protected void onResume() {
super.onResume();
// Dataset has changed, notify adapter !
mAdapter.notifyDataSetChanged();
}

Related

ListView in Fragment not refreshing

I have a custom ListView inside a fragment that represents a list of activities. Each activity is saved in a database (I'm using Parse), and the ListView is populated with the Activities from the database. There is an add button in the fragment that takes the user to an screen where he/she can create a new Activity object. When the user is done, the activity is finished (I call finish() on the Activity), and the fragment is brought back up. The problem is that the ListView doesn't refresh- it's the same list before the user was sent to the Activity Create screen.
I tried to override the onStart and onResume in my fragment class and call notifyDataSetChanged() or invalidateViews() but neither method works, the list view doesn't refresh so it includes the new Activity that was just created by the user.
Start the activity that adds Activity with startActivityForResult(). Override the onActivityResult() in your listview fragment to get notified when the user has finished adding an Activity. Then, refresh your ListView by querying the database again or adding the new Activity to the adapter (depending on how you implemented the listview adapter).
In your case it looks like you forget to refill the activity list attached to adapter from which listview generate views.
Refill the list again from scratch and then call notifyDataSetChanged();. Your listview will be updated with new entries.
Cheers

Android Fragments default select first item in ListView

In Android Studio I have selected a new project based on master / detail flow. The project works as it should be. Now I want to extend it. As of now the content of the items in the detail fragment are only shown when I click an item on the list. I want that the top item is selected automaticaly when the app starts. I thought I put in ItemListFragment just a method call
#Override
public void onStart()
{
mCallbacks.onItemSelected(DummyContent.ITEMS.get(0).id);
}
that a click is simulated in the lifecycle once all objects are initialized. That fails. What is the best way of doing this?
You can select the first element by the following code
yourListView.setSelection(0);
yourListView.getSelectedView().setSelected(true);
Hope this helps. Cheers mate! :)
You can use SharedPreferences. You can save first item of listview as preference when create listview, then you can use it later.
Have you try it in onResume()? I always put it in onResume()
UPDATE #1
You can try my way to implement the selection. Normally i don't use the select of list view.
1.In your data model, create a boolean field called "selection".
2.When you apply data to your adapter, set the first data "selection" to true.
3.In your adapter getView callback, try to handles your data "selection" such as:
if (!dummyData.selection){
do something when not select....
}else{
do something when selected...
}
UPDATE #2
put this code in ItemListFragment
#Override
public void onResume() {
super.onResume();
mCallbacks.onItemSelected(DummyContent.ITEMS.get(0).id);
}

Fragment refreshing on backpress

I have an activity MainActivity there are three fragments associated with this activity.
Now one of my fragment Timeline has a listview. Which I populate from a Database in the backend. I use an AsyncTask to fetch values from the DB and process them to the List. I trigger this AsyncTask in the onCreate of the Fragment Timeline.
Now from Timeline on click of any list item I navigate to a different Activity called as DetailActivity
The problem is whenever I press back from the DetailActivity the onCreate of my MainActivity is called and my list refreshes again - the whole DB operation is called again and my list does not retain its state.
I am calculating the visible items of my List before I navigate away from the Fragment but I am forced to use static values for these variables so that I retain the position. How to avoid this?
Below are the snippets of my onPause and onResume as laid down in the fragment Timeline
static int index;
static int top;
#Override
public void onPause(){
System.out.println("onPause");
index = lv.getFirstVisiblePosition();
View v = lv.getChildAt(0);
top = (v == null) ? 0 : v.getTop();
super.onPause();
uiHelper.onPause();
}
#Override
public void onResume(){
super.onResume();
//dbHelper.open();
System.out.println("onResumr");
lv.setSelectionFromTop(index, top);
ActionBar actionBar = getActivity().getActionBar();
actionBar.setTitle("Timeline");
uiHelper.onResume();
AppEventsLogger.activateApp(getActivity());
updateUI();
}
This also forces my AsyncTask to run again and again, which is an overhead.
Edit:
The root of this problem - After struggling for so many days I borrowed a friends phone to test and all was sorted on this new phone. I found out that I had turned on the Do not keep Activities option in my Developer Settings. The Dumb me!!
This is, unfortunately, the default behavior of the Fragment class. A Fragment is destroyed whenever the containing Activity is paused, and recreated whenever the containing Activity is resumed. If you use an Activity instead of a Fragment for the list, you would not experience the same behavior. With an Activity:
AsyncTasks and/or web services would not be called again.
The list would show the previously scrolled position.
If you want the same behavior with a Fragment, you need to override the onSaveInstanceState() method. And while interesting, it is not a small amount of work.
EDIT:
Make sure the Do not keep Activities option is unselected in your phone's Developer Settings. This, though, does not change the essential behavior of the Fragment class that I have outlined above.
You can call setRetainInstance(true) on your fragment. The lifecycle will be slightly different though.
A nice view of a fragment's lifecycle is available here
http://corner.squareup.com/2014/10/advocating-against-android-fragments.html

Refresh all fragments content after returning from another activity

I have a drop down (connected with db) in every fragment (4 fragments in one fragment activity).
Problem is that when I come back from AddNew intent the drop down list still contains the previous data. All I want is to refresh the data in drop down(s).
I have tried writing the following code but it gets stuck in a loop calling it self again and again.
public void OnResume()
{
super.onResume();
this.finish();
startActivity(getIntent());
}
You need to call notifyDataSetChanged() on the Adapters of your Fragments when you want to refresh the data.

How to recreate the listview of a former ListFragment after pressing back button

I have a ListFragment with a listview in it, that contains a navigation-structure. By selecting an item of the list, the next navigation hierarchy stage should be displayed. And so on.
The next hierarchy stage is created by a new fragment (remove the old fragment and add the same fragment new via fragmant transactions by using addToBackStack), in which the arrayadapter of the new listview is updated to the items of the next navigation hierarchy. That work pretty fine.
I want the user to have the possibility to navigate back via the back button. And here start my problems. I have no clue how to save the listview so it could be recreated after using the back button.
I thought using onSaveInstanceState would be a good idea. But onSaveInstanceState ist not called when the transaction gets comitted. I checked it by placing a Log.d("..","...) in the method. It´s not called. (What I found out, is, that onSaveInstanceState is called when rotating from portrait- to landscape-view and vice-versa. But that´s no help for my problem).
So what would be the best idea to store the elements of the listview and get it back to recreate the listview after using the back button and the former fragment is getting created? All items are Strings that are stored in an ArrayList that is bound to the ListAdapter.
Here my code. I implemented an interface, via the click on an item in the listview calls a method in the parent-activity. In this method I first call a method to fill the already existing ArrayList (navigationsItems) with the new items that are content of the next navigation-stage:
The code of my ArrayAdapter:
arrayAdapterFuerNaviList = new ArrayAdapter<String>(
BRC_BoardOverviewActivity.this,
android.R.layout.simple_list_item_1,
navigationsItems);
In this method I first call a method to fill an ArrayList (navigationsItems) with the items of the next navigation-stage:
// load new itemlist to navigation-
public void inhaltAktuelleNaviListeInArrayLaden() {
navigationsItems.clear();
for (int i = 0; i < prefs.getInt("aktuelleNaviListe_size", 0); i++) {
(...)
navigationsItems.add(titel);
}
}
Then I call the method, with which I load the new ListFragment and bind the new ArrayAdapter to it:
// push navifragment to BackStack and create a new instance of it
public void naviFragmenteNeuLaden() {
// get a reference to the actual ListFragment
Fragment removefragment = frgm.findFragmentById(R.id.navi_container);
// initialize ne ListFragment
BRC_NavigationsFragment navifragment = (BRC_NavigationsFragment) frgm
.findFragmentById(R.id.navi_container);
// remove the old and bind the new ListFragment from/to the container ...
FragmentTransaction frgmta = frgm.beginTransaction();
frgmta.remove(removefragment);
frgmta.add(R.id.navi_container, navifragment);
// ... push the old ListFragment on the BackStack and commit ...
frgmta.addToBackStack(null);
frgmta.commit();
frgm.executePendingTransactions();
// ... bind the updated ArrayAdapter to the new ListFragment ...
try {
navifragment.setListAdapter(arrayAdapterFuerNaviList);
} catch (Exception e) {
// TODO
e.printStackTrace();
}
// ... and notify
try {
arrayAdapterFuerNaviList.notifyDataSetChanged();
} catch (Exception e) {
// TODO
e.printStackTrace();
}
}
As mentioned, forward-navigating is no problem. But when i press back button for e.g. in the 2nd navigation-stage, the former ListFragment gets loaded (verfified with Log.d("..."."...)-Messages in onCreatView() of ListFragment), but the former listview which was in it isn´t created.
I am currently working on a new approach. When you click on an item in the list, I write the current list, together with a reference to the current ListFragment into a vector based stack. Then I catch with "onBackPressed()"-method the press of the back button. So now when the button is pressed, I call on the already mentioned methods (see above), write the item-data from the stack back into the list, call via the stored reference the forme ListFragmt and bind the updated ArrayAdapter to it. This is work in progress actually. I will write the result of this approach when finished.
I solved the problem.
For the different navigation contents of the ListView I have defined a class "Naviliste", in which all the items are stored. If someone clicks on an item, then the a new listview with the correspondingly new list will be generated. These lists are indexed, so each list get´s a fixed ID assigned.
By clicking an item in the ListView, the ID of the current Naviliste is pushed onto a stack. After that a new fragment will be created an the new list bound to it. The same procedure repeats if the user goes a step further, and so on ...
If the user pushes the back button to go a step back, the following is done:
The push of the back button is catched via the onPressedBack()-method placed in the parent activity. Via this method an own method is called. This pulls the last ID that was pushed onto the stack and then builds with it in a new created fragment the former list.
At the same time I will run along a counter that counts in which navigation depth I am. In each navigation step forward it get´s inceased by 1. And in reverse just reduced by 1. With this counter I am able to query if the user is in the navigation-root (counter = 0) and once more pushes the back button to leave the current activity. If so, i call finish() and the parent activity with its fragments get´s closed. Voilá!
It works great. Took a little bit time to get over it. But now I am happy that my solution works. :)

Categories

Resources