Why does saveStateInstance not work on screen orientation? - java

I am making a tour guide app that is made up of one main activity with and two fragments. The top fragment contains a list of cities and when you clock on a city the bottom fragment displays a description of that city. The problem is that when I change orientation I get an error saying "Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference"
Here is the city list fragment:
package com.example.tourguide;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
/**
* A simple {#link Fragment} subclass.
*/
public class CityFragment extends Fragment {
View view;
String[] cities;
String[] descriptions;
ListView listView;
DescriptionFragment text;
int mPosition;
public CityFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of member from saved state
text = (DescriptionFragment) getFragmentManager().getFragment(savedInstanceState, getString(R.string.DESCRIPTION_FRAG));
mPosition = savedInstanceState.getInt(getString(R.string.POSITION));
cities = savedInstanceState.getStringArray(getString(R.string.CITY_ARRAY));
descriptions = savedInstanceState.getStringArray(getString(R.string.DESCRIPTION_ARRAY));
text.change(descriptions[mPosition], cities[mPosition]);
}
// Get views
this.view = inflater.inflate(R.layout.fragment_city, container, false);
cities = getResources().getStringArray(R.array.cities);
descriptions = getResources().getStringArray(R.array.cities_description);
listView = this.view.findViewById(R.id.city_list);
// Create an ArrayAdapter
ArrayAdapter<String> listViewAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, cities);
// Set adapter on the listView
listView.setAdapter(listViewAdapter);
// Set an item click listener for ListView
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Get the selected item text from ListView
text = (DescriptionFragment) getFragmentManager().findFragmentById(R.id.fragmentBottom);
text.change(descriptions[Integer.parseInt(String.valueOf(position))], cities[Integer.parseInt(String.valueOf(position))]);
mPosition = position;
}
});
// Inflate the layout for this fragment
return this.view;
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
// Save the fragments Instance
getFragmentManager().putFragment(outState, getString(R.string.DESCRIPTION_FRAG), text);
outState.putInt(getString(R.string.POSITION), mPosition);
outState.putStringArray(getString(R.string.CITY_ARRAY), cities);
outState.putStringArray(getString(R.string.DESCRIPTION_ARRAY), descriptions);
}
}
And here is the description fragment:
package com.example.tourguide;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* A simple {#link Fragment} subclass.
*/
public class DescriptionFragment extends Fragment {
TextView cityName;
TextView text;
public DescriptionFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (savedInstanceState != null) {
}
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_description, container, false);
text = view.findViewById(R.id.city_description);
cityName = view.findViewById(R.id.city_name);
return view;
}
public void change(String description, String city) {
text.setText(description);
cityName.setText(city);
}
}
The text.change method seems to be where the problem lies but how else can I implement it to save the description state?
if (savedInstanceState != null) {
// Restore value of member from saved state
text = (DescriptionFragment) getFragmentManager().getFragment(savedInstanceState, getString(R.string.DESCRIPTION_FRAG));
mPosition = savedInstanceState.getInt(getString(R.string.POSITION));
cities = savedInstanceState.getStringArray(getString(R.string.CITY_ARRAY));
descriptions = savedInstanceState.getStringArray(getString(R.string.DESCRIPTION_ARRAY));
text.change(descriptions[mPosition], cities[mPosition]);
}

Why don't you just store the state within the DescriptionFragment.
/**
* A simple {#link Fragment} subclass.
*/
public class DescriptionFragment extends Fragment {
private static final String DESCRIPTION = "DESCRIPTION";
private static final String CITY = "CITY";
TextView cityName;
TextView text;
public DescriptionFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_description, container, false);
}
#Override
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
text = view.findViewById(R.id.city_description);
cityName = view.findViewById(R.id.city_name);
if (savedInstanceState != null) {
String description = savedInstanceState.getString(DESCRIPTION);
String city = savedInstanceState.getString(CITY);
change(description, city);
}
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
// Save the fragments Instance
outState.putString(DESCRIPTION, text.getText().toString());
outState.putString(CITY, cityName.getText().toString());
}
public void change(String description, String city) {
text.setText(description);
cityName.setText(city);
}
}

Can use the property in your xml AndroidManifest.xml
android:configChanges="keyboardHidden|orientation"
Here it will indicate to the application that you will be in charge of handling a rotation and will not restart your activity so that there is no null data.

Related

How can I get the position of the list item clicked while using Firebase RecyclerAdapter

I am using Firebase RecyclerAdapter rather than using the normal RecyclerAdapter. I wanted to store the position of the list Item which is clicked.
The code for the HomeFragment is below
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.FirebaseDatabase;
/**
* A simple {#link Fragment} subclass.
* Use the {#link HomeFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class HomeFragment extends Fragment {
private static final String TAG = "HomeFragment";
private RecyclerView recyclerView;
private ProductAdapter adapter;
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public HomeFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment HomeFragment.
*/
// TODO: Rename and change types and number of parameters
public static HomeFragment newInstance(String param1, String param2) {
HomeFragment fragment = new HomeFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v= inflater.inflate(R.layout.fragment_home, container, false);
recyclerView = v.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
String u = FirebaseAuth.getInstance().getCurrentUser().getUid();
FirebaseRecyclerOptions<Product> options = new FirebaseRecyclerOptions.Builder<Product>()
.setLifecycleOwner(this)
.setQuery(FirebaseDatabase.getInstance().getReference().child(u).child("Products"), Product.class)
.build();
adapter = new ProductAdapter(options);
recyclerView.setAdapter(adapter);
return v;
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onStop() {
super.onStop();
}
}
The code for the ProductAdapter class is given below
package com.example.prj;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.squareup.picasso.Picasso;
public class ProductAdapter extends FirebaseRecyclerAdapter<Product, ProductAdapter.ProductViewHolder> {
private static final String TAG = "ProductAdapter";
ImageView btn_stock;
public ProductAdapter(#NonNull FirebaseRecyclerOptions<Product> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull ProductViewHolder holder, int position, #NonNull Product model) {
holder.pname.setText(model.getPname());
holder.price.setText(model.getPrice());
holder.description.setText(model.getDescription());
Picasso.get().load(model.getImage()).into(holder.image);
}
#NonNull
#Override
public ProductViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_row, parent, false);
return new ProductViewHolder(view);
}
class ProductViewHolder extends RecyclerView.ViewHolder{
TextView pname, price, description;
ImageView image ;
public ProductViewHolder(#NonNull final View itemView) {
super(itemView);
pname = itemView.findViewById(R.id.product_list_name);
price = itemView.findViewById(R.id.product_list_price);
description = itemView.findViewById(R.id.product_list_description);
image = itemView.findViewById(R.id.product_list_image);
}
}
Using the position of the list item which is clicked I want to make the list item expandable.Like the users clicks on the list item and the list item expands and shows some more details about that item..If someone has the solution for that please help me in that also..
In onBindViewHolder() set the item click listener:
#Override
protected void onBindViewHolder(#NonNull ProductViewHolder holder, int position, #NonNull Product model) {
.....
.....
....
//here set the click of the item
holder.view.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
//here do something with position that is passed in the onBindViewHolder
//if you clicked item 1 the position is 0
//if you clicked item 2 the position is 1
..............
Log.d("POSITION" , String.valueOf(position));
}
});
In your Viewholder add the view parameter
class ProductViewHolder extends RecyclerView.ViewHolder{
TextView pname, price, description;
ImageView image ;
//here
View view;
public ProductViewHolder(#NonNull final View itemView) {
super(itemView);
//set it here
view = itemView;
......
......

I don't get how to get the value of my EditText in my custom Dialog

I have to do a small app for a school project on Android, and I wanted to update my listView through a Fullscreen Dialog but I can't find a way to get the values inside my EditText fields to put add them to my ArrayLists.
Here is the code of my Dialog class:
package com.example.memo;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.TextView;
import java.util.ArrayList;
#SuppressLint("ValidFragment")
public class FullscreenDialog extends DialogFragment implements View.OnClickListener {
private EditText titleEdit;
private EditText infoEdit;
private EditText fullEdit;
private ArrayList<String> titleArray;
private ArrayList<String> infoArray;
private ArrayList<Integer> imageArray;
private ArrayList<String> fullArray;
private Callback callback;
public FullscreenDialog(ArrayList<String> titleArray, ArrayList<String> infoArray, ArrayList<String> fullArray, ArrayList<Integer> imageArray){
this.titleArray = titleArray;
this.infoArray = infoArray;
this.fullArray = fullArray;
this.imageArray = imageArray;
}
static FullscreenDialog newInstance(ArrayList<String> titleArray, ArrayList<String> infoArray, ArrayList<String> fullArray, ArrayList<Integer> imageArray) {
return new FullscreenDialog(titleArray,infoArray,fullArray,imageArray);
}
public void setCallback(Callback callback) {
this.callback = callback;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NORMAL, R.style.FullscreenDialogTheme);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_fullscreen_dialog, container, false);
ImageButton close = view.findViewById(R.id.fullscreen_dialog_close);
TextView action = view.findViewById(R.id.fullscreen_dialog_action);
EditText titleEdit = view.findViewById(R.id.fullscreen_dialog_title);
EditText infoEdit = view.findViewById(R.id.fullscreen_dialog_info);
EditText fullEdit = view.findViewById(R.id.fullscreen_dialog_full);
close.setOnClickListener(this);
action.setOnClickListener(this);
return view;
}
#Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.fullscreen_dialog_close:
dismiss();
break;
case R.id.fullscreen_dialog_action:
this.titleArray.add(titleEdit.getText().toString());
this.infoArray.add(infoEdit.getText().toString());
this.fullArray.add(fullEdit.getText().toString());
this.imageArray.add(R.drawable.ic_launcher_foreground);
callback.onActionClick("Memo saved!");
dismiss();
break;
}
}
public interface Callback {
void onActionClick(String name);
}
}
I guess I must have made some mistakes on the way I used findViewById or something, but Android is kind of new for me and I can't seem to find where it's wrong.
titleArray, infoArray and fullArray are the ArrayLists in which is stored my data.
imageArray is my ArrayList for my images IDs.
You calling or making use of an instance variable (i.e fullEdit, titleEdit etc) that is not initialised. To correct this initialised them in method onCreateView, so it should look like this
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_fullscreen_dialog, container, false);
ImageButton close = view.findViewById(R.id.fullscreen_dialog_close);
TextView action = view.findViewById(R.id.fullscreen_dialog_action);
titleEdit = view.findViewById(R.id.fullscreen_dialog_title);
infoEdit = view.findViewById(R.id.fullscreen_dialog_info);
fullEdit = view.findViewById(R.id.fullscreen_dialog_full);
close.setOnClickListener(this);
action.setOnClickListener(this);
return view;
}
With the above the class instance EditText variables are instantiated and can be use to get the text onClick method
You define the variables titleEdit, infoEdit and full Edit globally in the class but the problem is that you defined them again locally in the onCreateView method and you assigned them to the view by using findViewById .
So you have 2 kind of variable now :
the global ones ( doesn't linked yet )
the local ones ( linked to the view )
When you try to get the value of the editText you accessed to the global ones that is not linked to the View .
To solve that delete the local ones. you onCreateView should look like this :
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_fullscreen_dialog, container, false);
ImageButton close = view.findViewById(R.id.fullscreen_dialog_close);
TextView action = view.findViewById(R.id.fullscreen_dialog_action);
titleEdit = view.findViewById(R.id.fullscreen_dialog_title);
infoEdit = view.findViewById(R.id.fullscreen_dialog_info);
fullEdit = view.findViewById(R.id.fullscreen_dialog_full);
close.setOnClickListener(this);
action.setOnClickListener(this);
return view;
}

Android: FragmentManager returns blank fragment layout when new Fragment is inflated - onCreateView() method is not called at all

Hi my fragment does not get inflated inside a frame layout. please help here is my code:
My MainActivity extends AppCompatActivity and not FragmentActivity because i need to use actionbar.
public void showFragmentWomen(String title) {
showFragment(FragmentWomen.newInstance(title), false);
}
private void showFragment(Fragment fragment, boolean allowStateLoss) {
FragmentManager fm = mFragmentManager;
FragmentTransaction ft = fm.beginTransaction().replace(R.id.container, fragment);
ft.addToBackStack(null);
if (allowStateLoss || !BuildConfig.DEBUG) {
ft.commitAllowingStateLoss();
} else {
ft.commit();
}
fm.executePendingTransactions();
}
Fragment code:
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.res.ResourcesCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.android.msahakyan.angesbags.R;
/**
* A simple {#link Fragment} subclass.
* Use the {#link FragmentWomen#newInstance} factory method to
* create an instance of this fragment.
*/
public class FragmentWomen extends Fragment {
private static final String KEY_MOVIE_TITLE = "key_title";
private Spinner spinner1;
public FragmentWomen() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment.
*
* #return A new instance of fragment FragmentWomen.
*/
public static FragmentWomen newInstance(String movieTitle) {
FragmentWomen fragmentWomen = new FragmentWomen();
return fragmentWomen;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_women, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
spinner1 = (Spinner) view.findViewById(R.id.frag_women_spinner);
spinner1.setOnItemSelectedListener(new CustomOnItemSelectedListener());
}
public class CustomOnItemSelectedListener implements AdapterView.OnItemSelectedListener {
String firstItem = String.valueOf(spinner1.getSelectedItem());
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (firstItem.equals(String.valueOf(spinner1.getSelectedItem()))) {
// ToDo when first item is selected
} else {
Toast.makeText(parent.getContext(),
"You have selected : " + parent.getItemAtPosition(pos).toString(),
Toast.LENGTH_LONG).show();
}
}
#Override
public void onNothingSelected(AdapterView<?> arg) {
}
}
}

Access method in class

How can i call the listview method out of the FragmentTwo class? I'm using a NavDrawer which is fragment-based, so i have to initiate the ListView in the FragmentTwo class.
This is my code:
package xy;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class FragmentTwo extends Fragment {
View rootview;
private Context context;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootview = inflater.inflate(R.layout.fragment_two, container, false);
return rootview;
list.this.listview();
}
class list extends MainActivity{
public void listview(){
String[] listcontent = {"Test1","text2","text4"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, getView().R.layout.listviewcontent, listcontent);
ListView listView = (ListView) getView().findViewById(R.id.list);
listView.setAdapter(adapter);
}
public void registerClickCallback() {
ListView listView = (ListView) findViewById(R.id.list);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView textView = (TextView) view;
String message = "You clicked # " + position + " which is:" + textView.getText().toString();
Toast.makeText(list.this, message, Toast.LENGTH_LONG).show();
}
});
}
}
}
My main problem is the error message
.....is not an enclosing class
when calling list.this.listview(); from the onCreate method.
This isn't the right way to call methods in your Fragment's parent Activity.
You can get the parent Activity with:
MainActivity activity = (MainActivity) getActivity();
And you can then access its methods in this style:
activity.callSomeMethodInYourActivity();
Update:
Also your onCreateView() throws an "unrechable statement" error because you have code after the return statement. This code can't be executed because the method is quit when the return statement is reached.
Complete solution:
Place this in your MainActivity.java file:
public void listview(){
String[] listcontent = {"Test1","text2","text4"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, getView().R.layout.listviewcontent, listcontent);
ListView listView = (ListView) getView().findViewById(R.id.list);
listView.setAdapter(adapter);
}
public void registerClickCallback() {
ListView listView = (ListView) findViewById(R.id.list);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView textView = (TextView) view;
String message = "You clicked # " + position + " which is:" + textview.getText().toString();
Toast.makeText(list.this, message, Toast.LENGTH_LONG).show();
}
});
}
And your fragment should look like this:
public class FragmentTwo extends Fragment {
View rootview;
private Context context;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootview = inflater.inflate(R.layout.fragment_two, container, false);
MainActivity activity = (MainActivity) getActivity();
activity.listview()
return rootview;
}
}
After all I don't really understand why you are not placing the listview() and registerClickCallback() methods directly in your Fragment. IMHO this would make more sense...

onSaveInstanceState is not being called in Fragment

I know that people have asked this question, but I followed all the answers and I still have the same problem. I have two scripts One is the fragment manager (IngredientsActivity) and the other is the fragment (OtherList). The code is as follows
IngredientsActivity
import java.util.ArrayList;
import android.app.ActionBar;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class IngredientsActivity extends FragmentActivity implements ActionBar.TabListener {
private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.check_list);
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// For each of the sections in the app, add a tab to the action bar.
actionBar.addTab(actionBar.newTab().setText("Alcahol").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("Juice").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("Other").setTabListener(this));
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
getActionBar().setSelectedNavigationItem(savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); //OVERRIDE SAVE ON MAINCLASS
outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar().getSelectedNavigationIndex());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
if (tab.getPosition() == 0) {
AlcoholList simpleListFragment = new AlcoholList();
getSupportFragmentManager().beginTransaction().replace(R.id.containert, simpleListFragment).commit();
}
else if (tab.getPosition() == 1) {
JuiceList androidlidt = new JuiceList();
getSupportFragmentManager().beginTransaction().replace(R.id.containert, androidlidt).commit();
}
else {
OtherList androidversionlist = new OtherList();
getSupportFragmentManager().beginTransaction().replace(R.id.containert, androidversionlist).commit();
}
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
public static class DummySectionFragment extends Fragment {
public DummySectionFragment() {
}
public static final String ARG_SECTION_NUMBER = "section_number";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TextView textView = new TextView(getActivity());
textView.setGravity(Gravity.CENTER);
Bundle args = getArguments();
textView.setText(Integer.toString(args.getInt(ARG_SECTION_NUMBER)));
return textView;
}
}
}
OtherList
import java.util.ArrayList;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
public class OtherList extends ListFragment{
MyCustomAdapter dataAdapter = null;
private ArrayList<String> recipesList;
private ArrayList<Items> stateList ;
public OtherList() {
setRetainInstance(true);
stateList = new ArrayList<Items>();
Items _states1 = new Items ("Gin",false);
stateList.add(_states1);
Items _states2 = new Items ("Ginger Liqueur",false);
stateList.add(_states2);
Items _states3 = new Items ("Citrus Vodka",false);
stateList.add(_states3);
Items _states4 = new Items ("Champagne",false);
stateList.add(_states4);
Items _states5 = new Items ("Coconut Rum",false);
stateList.add(_states5);
Items _states6 = new Items ("Pear Vodka",false);
stateList.add(_states6);
Items _states7 = new Items ("Rum",false);
stateList.add(_states7);
Items _states8 = new Items ("Tequila",false);
stateList.add(_states8);
Items _states9 = new Items ("Triple Sec",false);
stateList.add(_states9);
Items _states10 = new Items ("Kahlua",false);
stateList.add(_states10);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dataAdapter = new MyCustomAdapter(this.getActivity(),R.layout.da_item, stateList);
setListAdapter(dataAdapter);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.list_fragment, container, false);
}
#Override
public void onListItemClick(ListView list, View v, int position, long id) {
}
private class MyCustomAdapter extends ArrayAdapter<Items>
{
private ArrayList<Items> stateList;
public MyCustomAdapter(Context context, int textViewResourceId,
ArrayList<Items> stateList)
{
super(context, textViewResourceId, stateList);
this.stateList = new ArrayList<Items>();
this.stateList.addAll(stateList);
}
private class ViewHolder
{
CheckBox name;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
Log.v("ConvertView", String.valueOf(position));
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.da_item, null);
holder = new ViewHolder();
holder.name = (CheckBox) convertView.findViewById(R.id.ingredientbox);
convertView.setTag(holder);
holder.name.setOnClickListener( new View.OnClickListener()
{
public void onClick(View v)
{
CheckBox cb = (CheckBox) v;
Items _state = (Items) cb.getTag();
_state.setSelected(cb.isChecked());
}
});
}
else
{
holder = (ViewHolder) convertView.getTag();
}
Items state = stateList.get(position);
holder.name.setText(state.getName());
holder.name.setChecked(state.isSelected());
holder.name.setTag(state);
return convertView;
}
}
#Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
}
#Override
public void onSaveInstanceState(Bundle outState) {
Log.d("hey","SAVING"); //NOT SAVING
super.onSaveInstanceState(outState);
save();
outState.putStringArrayList("index", recipesList);
}
}
}
}
}
I found multiple suggestions that said to override the onSaveInstanceState , which I did and I found even more telling me to use setRetainInstance. I don't know why setRetainInstance state would be helpful if I want to save a value of a list. My question-Why Is it not calling the save in the OtherList class or whats a better method to implement if I want to save the values in the List View (in this case I am using checkboxes)
I had a similar problem where I was trying to get a Fragment to save its state but onSaveInstanceState() wasn't being called on FragmentTransaction.replace(). I was trying to find a solution for this and thought, if the Fragment itself can't save its own state then can't whatever is doing the replacing save it. So I did something like this:
In the Fragment have a method called getState() or whatever you want:
public Bundle getState()
{
// save whatever you would have in onSaveInstanceState() and return a bundle with the saved data
}
Then in the hosting object, save that bundle to its instance variables before replacing the Fragment and set the argument to that saved bundle when switching back.
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
// assume Fragment a exists and you're trying to save the state and "state" is an instance variable
state = a.getState();
ft.replace(android.R.id.content, b);
Then when swapping back to Fragment a you would pass the bundle as an argument.
a.setArguments(state);
ft.replace(android.R.id.content, a);
I didn't look into your code too deeply but it sounds similar to the problem I had from your description.
onSaveInstanceState() is only called when the Android system may need to recreate that particular instance of the Fragment. There are many instances of navigating away from the Fragment or even destroying the Fragment where it will not be called. Please consult the documentation for more information, please read the Activity.onSaveInstanceState() documentation as well since that applys here also: http://developer.android.com/reference/android/app/Fragment.html#onSaveInstanceState(android.os.Bundle)
http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)
EDIT: In your case, you must not recreate the fragment every time the user navigates back to the fragment. I recommend considering ViewPager and FragmentPagerAdapter to automatically manage the fragments. Also look at this post: ViewPager and fragments — what's the right way to store fragment's state?

Categories