I have an Activity with a ListView (ItemsActivity) which its contents come from a JSON API. When I press in one item in the ListView it loads another Activity with the details information (DetailActivity) . The problem is, when I press the Back Button, ItemsActivity reload the ListView again.
I don't know where I can find more information about this. I came from iOS where the previous screen is not reload every time.
I want to keep the ListView data between activities. I tested to call loadListItems() method from onResume() but same result.
Here is and brief sample of my code. Any help and suggestions will be really appreciated.
/* ItemsActivity.java */
public class ItemsActivity extends AppCompatActivity {
private ListView listItemView;
private Movie[] movies;
private ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler);
listItemView = (ListView) findViewById(R.id.listItemView);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
loadListItems();
}
private void loadListItems(){
// Http call
...
// Iterate JSON and saving to movies array
...
progressBar.setVisibility(INVISIBLE);
ListAdapter adapter = new ListAdapter(ItemsActivity.this, movies);
listItemView.setAdapter(adapter);
}
/* Adapter Class */
#Override
public void onClick(View v) {
Intent i = new Intent(this, DetailActivity.class);
i.putExtra("item_id", 1);
startActivity(i);
}
}
I just tested with a new Project with 2 Activities, ActivityOne and ActivityTwo. ActivityOne have a button, when a pressed its load ActivityTwo and when I press the back button, in ActivityOne the method onCreate() is called again.
You mentioned that "I tested to call loadListItems() method from onResume() but same result." This onResume() code is culprit.
OnResume() will get called whenever your activity gets focus again. If you are calling loadListItems() in onResume() then it will get called everytime you come back from your second activity to this activity.
http://developer.android.com/reference/android/app/Activity.html#onResume()
A solution is to use StartActivityForResult and not StartActivity. Then in the second activity, override the onBackPressed method and finish() the second activity within this method. Override the onActivityResult method in your first activity and this activity will be called and not the onCreate method and the ListView will not be reloaded.
The problem was only when I pressed the back button from Action Bar and I fix it with onOptionsItemSelected method.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
Related
I have two Activities A and B.
Activity A has a Tablayout with some Tabs. When I navigate from A to B I use this:
Intent intent = new Intent(A, B.class);
A.startActivity(intent);
When I now navigate back from B to A I have a question:
1) When using Android's back button, the selected tab / scrolling position from A was remembered
2) When using an Intent or NavUtils.navigateUpFromSameTask(this); then the selected tab and scroll Position is NOT remembered but set to initial value
Can someone explain me what is going on here?
1) when navigation from activity A to B, the android system does not destroy activity A, but takes it to the back stack and adds B to the foreground. thats why when you press the back button or call onBackPressed() from the java code activity B is destroyed and A is set to the foreground. here is an example from the docs : Understand Tasks and Back stack
2) when using an intent/navigateUpFromSameTask activity A is recreated and set to the foreground and B is set to the background, it's like adding another activity A to the stack so it will be A,B,A but if you press the back btn then you will be back to B and then A.
if you want to keep the scroll position and other data in activity A you call the onBackPressed in B or use the onSaveInstanceState to save the data and use it in the onCreate .
here is an example of saved instance:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("VariableName", variableData);
savedInstanceState.putString("VariableName", variableData);
savedInstanceState.putString("VariableName", variableData);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.penguin_main);
if(savedInstanceState!=null){
bookData = (String) savedInstanceState.getSerializable("VariableName");
bookData = (String) savedInstanceState.getSerializable("VariableName");
bookData = (String) savedInstanceState.getSerializable("VariableName");
}
}
You can set the current scroll position and tab position in activity A's on overriding onSaveInstance(Bundle savedInstanceState) method. When return to activity you can get onRestoreInstanceState(Bundle savedInstanceState) to restore it.
Hope it helps :)
Because NavUtils.navigateUpFromSameTask() just calls startActivity() and if android:launchMode="standard" the activity will be instantiated and created again and that is why can not remember the previous selected tab. To solve this issue you can override onNavigateUp() and inside that setCurrentItem(index) the index of tab you want to be displayed.
#Override
public boolean onNavigateUp() {
myViewPager.setCurrentItem(position, true);
return true;
}
Edit
You can use another solution to solve the problem by setting android:launchMode="singleTop" on activity but this solution may not applicable in all the application.
When you start an Activity, the first page will be opened! But when the back button is pressed, it navigates between the saved state of the activityTo simulate the back button pressed, you can try this:
#Override
public void onBackPressed() {
finish(); //your choice, thought not needed as super.onBackPressed(); is called if nothing is assigned here
}
or on toolbar back button clicked click:
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
I have created an Activity named BaseNavigationActivity that createsNavigationDrawer. All other activities are extending from this activity. It works fine,open the drawer on button click.
But when i go into another activity, and come back to previous Activity. The button stops working. Although visually button is still there, and if i click and drag from left side, it opens the Drawer Layout
When i debug it, i found out that it calls onRestart() and onResume() methods, but there is no code written in these method.
So do i need to add the code there as well? or is there any way to implement onClickListner in onRestart() and onResume() of Activity
onCreate()
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout_main);
headerLayout= (FrameLayout) findViewById(R.id.header_layout);
btnOpenDrawer= (Button) findViewById(R.id.btn_openDrawer);
homeLayout= (LinearLayout) findViewById(R.id.home_layout);
btnOpenDrawer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
drawerLayout.openDrawer(Gravity.LEFT);
}
});
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onRestart() {
super.onRestart();
}
Create class level ClickListener like onClickListener and Use it wherever you want.
// Activate Listener
myView.setOnClickListener(onClickListener);
// DeActivate Listener
myView.setOnClickListener(null);
// Listener
View.OnClickListener onClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
}
};
In my opinion the error is that you set your OnClickListener in the onCreate Method. The OnClickListener only gets set when you create the activity. When you switch to your second activity, the OnClickListener will get overwritten and when you go back to your first activity the OnClickListener will not be set, because the first activity was already created, and only onResume will get called.
Try to move your code from the onCreate to onResume, so the listener will get set every time the activity is moving back to the front.
I have a listview of shopping lists in a fragment and when I click one I get a new activity that shows a listview with all the products in the clicked shopping list. What I am trying to do is to add products this list by selecting some checkboxes in the newly created activity and pass them to the previous activity.
public class DisplayShoppingListDetailsActivity extends AppCompatActivity{
private ShoppingList list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//defines the activity layout
setContentView(R.layout.shopping_list_details);
ListView listView = (ListView) findViewById(R.id.shopping_list_details);
Intent intent = getIntent();
list = (ShoppingList) intent.getSerializableExtra("ShoppingList");
ProductsOnListAdapter ad = new ProductsOnListAdapter(this, -1, Service.getService().getProductsOnList(list));
listView.setAdapter(ad);
FloatingActionButton button = (FloatingActionButton) findViewById(R.id.floatingButton);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivityForResult(new Intent(DisplayShoppingListDetailsActivity.this, ListOfProductsActivity.class));
//This method here is not working...it says it cannot resolve the method
}
});
}
You really should not have one activity try to modify another activity's instance. That will lead to bugs in your code.
Instead, in the first activity, you can use startActivityForResult() to launch the second activity, then the second activity can use setResult() to return data to the first activity. This is all documented if you read the javadoc for Activity under the heading "Starting Activities and Getting Results".
I have a Activity that transitions between fragments. Fragment 1 to fragment 2. Fragment 1 has a listview. When the user goes to fragment 2 the user has the option to make changes to the data that fills the listview. When the user presses the back button it takes them back to the first fragment. When the user returns the listview has to be updated to show the changes that were made in fragment 2. How can i do this?
Frag2 pfrag = new Frag2();
pfrag.setArguments(bundle);
ft=fm.beginTransaction();
ft.add(R.id.fragment_swap, pfrag,"Profile");
ft.show(pfrag);
ft.addToBackStack("pfrag");
ft.commit();
You would do this by calling notifyDataSetChanged(); on the ListView's adapter.
For more info
You could use Robins answer or if you want to pass the data in fragment 2 to fragment 1 you could call a method in fragment 1 class:
YourFragmentClass.refreshList( your data)
and in Fragment 2 the method:
puplic void refreshList(your data) {
// set the adapter with your data
}
In you fragment, include the code as like below.
(isPaused)boolean variable is used to track current fragment is paused while navigating to next activity.
While resuming back call the webservice (or) call the method to refresh the list by calling notifydatasetchanged() from adapter.
#Override
public void onResume() {
super.onResume();
if(isPaused) {
isPaused=true;
fetchDirectories();
// call the adapter method to notify the data set.
}
}
#Override
public void onPause() {
super.onPause();
isPaused=true;
}
private boolean isPaused=false;
I think the best way to achieve this, is to load the list in the fragment's onResume()-Method. So, the code looks something like this:
#Override
public void onResume() {
super.onResume();
initializeList();
}
...
private void initializeList() {
adapter = new MessageTemplateAdapter(getActivity(), datasource.getTemplateList());
setListAdapter(adapter);
}
I have an Activity named A,
in this, a ListView and one button are there.After clicking on this button,List View is shown and from this list view, by clicking on a its items, I can move to Activity B.
Now the problem is this when I come back from Activity B -> Activity A then, I see the Button only not the list view.
because I am calling intent of Activity A..
Code
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
Intent i;
i = new Intent(B.this, A.class);
startActivity(i);
finish();
super.onBackPressed();
}
In Activity B, I have the above implementation and i am using finish() in On Pause() condition also.
I want to see the List View with buttons.
Do i need to call whole code again to show the ListView or is there any other way to resolve this problem??
Is there any way to save the previous activity view?
Its because you are finishing Activity A before switching to Activity B. If you want your ListView as it is then do not finish Activity A and then try. If still your data does not visible then bind your listview again in onResume() of Activity A.
//removed finish().
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
Intent i = new Intent(B.this, A.class);
startActivity(i);
super.onBackPressed();
}
You are creating your activity aagain since u hv called the finish
method and when u go back it calls onCreate rather it should call
onResume method of lifecycle.
Just do one thing.rmove finish() from your code
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
Intent i;
i = new Intent(B.this, A.class);
startActivity(i);
super.onBackPressed();
}
onResume called when activity start or when you return from another activity as per life cycle of Activity, its better to keep your code inside onResume, which will refill your listview with data.
SO when you called activity B from A (in Activity A fill your listview inside onResume method) and when you press back, its again callon onResume and fill your listview.
Instead# doing code inside onBackPressed of activity B.