I am new to Android and have an integer weekNumber that needs to be kept when closing the app. My idea was to set the value in the activity that handled the fragments that need to use the value, and always get the value from there with a getter, but the weekNumber keeps resetting when I close the app or switch fragments, even though I use SharedPreferences. I load the saved data in onCreate of the activity, and save the data in onPause. Maybe this is wrong. Why does this happen? I would appreciate any help and would love to learn more!
Here is my MainActivity that handles Fragments:
public class MainActivity extends AppCompatActivity {
private int weekNumber;
private static final String SHARED_PREFS = "sharedPrefs";
private static final String WEEK_NUMBER = "weekNumber";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigation);
bottomNavigationView.setOnNavigationItemSelectedListener(navListener);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,new HomeFragment()).commit();
loadData();
}
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()) {
case R.id.nav_home:
selectedFragment = new HomeFragment();
break;
case R.id.nav_add:
selectedFragment = new CalculatorFragment();
break;
case R.id.nav_settings:
selectedFragment = new SettingsFragment();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,selectedFragment).commit();
return true;
}
};
#Override
protected void onPause() {
super.onPause();
saveData();
}
public void saveData() {
SharedPreferences sharedPreferences = getSharedPreferences(SHARED_PREFS,MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt(WEEK_NUMBER,weekNumber);
}
public void loadData() {
SharedPreferences sharedPreferences = getSharedPreferences(SHARED_PREFS,MODE_PRIVATE);
weekNumber = sharedPreferences.getInt(WEEK_NUMBER,1);
}
public int getWeekNumber() {
return weekNumber;
}
public void setWeekNumber(int weekNumber) {
this.weekNumber = weekNumber;
}
One of the Fragments:
public class HomeFragment extends Fragment {
View rootView;
private TextView[] textViews;
MainActivity mainActivity = new MainActivity();
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_home,container,false);
textViews = new TextView[16];
for(int i=0; i<textViews.length; i++) {
{
String buttonID = "textView" + (i+1);
int resID = getResources().getIdentifier(buttonID, "id", getActivity().getPackageName());
textViews[i] = ((TextView) rootView.findViewById(resID));
}
}
setWeekText();
textViews[9].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(getActivity(),ActivityDay1.class));
}
});
Button buttonNextWeek = rootView.findViewById(R.id.buttonNextWeek);
buttonNextWeek.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mainActivity.setWeekNumber(mainActivity.getWeekNumber()+1);
setWeekText();
}
});
return rootView;
}
private void setWeekText() {
textViews[8].setText(String.valueOf(mainActivity.getWeekNumber()));
}
Call editor.apply(); at the end of your saveData function in order to actually save the value in the SharedPreferences.
Also, you can't call MainActivity mainActivity = new MainActivity(); in the fragment. Set it with mainActivity = getActivity(); in onCreateView or directly in your onClick listeners.
Why? What you have creates a new instance of MainActivity inside the fragment rather than referring to the one on which you have set the data you need.
Also, if you keep the current design, it's probably safer to call loadData in your Activity onCreate before you create the fragment that is going to try to access the data.
Perhaps a better option would be to just use the shared preferences in the fragment directly though.
A couple of things.
You need to make sure data is actually being saved. Add editor.commit()in your saveData()
You should do the saving in onSaveInstance and restoring in onSaveInstance since this is what android will call when the system kill your activity on cases such as low memory
Related
I have used MVVM architecture in fragment the networking call are working perfect and the UI are updated correctly. I load the fragment from previous fragment there is a back button when I click on back button it give error "No View found for ID #6722734". the Interesting thing when I remove the MVVM code then Its going back to previous fragment perfectly. Anyone expert can help I would really appreciate.
private HealthGoalViewModel healthGoalViewModel;
private FragmentHealthGoalBinding fragmentHealthGoalBinding;
private boolean valid = false;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_health_goal, container, false);
fragmentHealthGoalBinding = DataBindingUtil.setContentView(getActivity(), R.layout.fragment_health_goal);
healthGoalViewModel = new HealthGoalViewModel(getActivity());
fragmentHealthGoalBinding.setHealthViewModel(healthGoalViewModel);
fragmentHealthGoalBinding.tvName.setText(GeneralUtilities.getSharedPreferences(getActivity()).getString("user_name", ""));
fragmentHealthGoalBinding.setPresenter(new Presenter() {
#Override
public void onClicked() {
String userId = GeneralUtilities.getSharedPreferences(getActivity()).getString("userID", "");
String strWeight = healthGoalViewModel.targetWeight.get();
String strDescription = healthGoalViewModel.description.get();
healthGoalViewModel.sendRequest(strWeight, strDescription, userId);
}
});
fragmentHealthGoalBinding.ivBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().onBackPressed(); // does not work
}
});
return view;
}
}
I'm calling the fragments from here
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.iv_back:
GeneralUtilities.connectFragmentWithoutBack(getActivity(), new DashboardFragment());
break;
case R.id.ll_body_composition:
GeneralUtilities.putIntValueInEditor(getActivity(), "highlighted_position", 1).commit();
GeneralUtilities.connectFragmentWithBack(getActivity(), new BodyCompositionFragment());
highlitedBackground();
break;
case R.id.ll_health_goal:
GeneralUtilities.putIntValueInEditor(getActivity(), "highlighted_position", 2).commit();
GeneralUtilities.connectFragmentWithBack(getActivity(), new HealthGoalFragment());
highlitedBackground();
break;
case R.id.ll_social_info:
GeneralUtilities.putIntValueInEditor(getActivity(), "highlighted_position", 3).commit();
GeneralUtilities.connectFragmentWithBack(getActivity(), new SocialInfoFragment());
highlitedBackground();
break;
case R.id.ll_health_info:
GeneralUtilities.putIntValueInEditor(getActivity(), "highlighted_position", 4).commit();
GeneralUtilities.connectFragmentWithBack(getActivity(), new HealthInformationFragment());
highlitedBackground();
break;
this is my GeneralUtilites Class
public class GeneralUtilities {
public static SharedPreferences sharedPreferences;
public static SharedPreferences.Editor editor;
public static Fragment connectFragmentWithoutBack(Context context, Fragment fragment){
((AppCompatActivity)context).getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,fragment).commit();
return fragment;
}
public static Fragment connectFragmentWithBack(Context context, Fragment fragment){
((AppCompatActivity)context).getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,fragment).addToBackStack("abc").commit();
return fragment;
}
}
I currently see a very strange nullpointer-exception that I can not explain myself.
I have an Activity which hosts two fragments.
The context-menu is evaluated in the host-activity and then calls a public function in one of the fragments.
While this works well for several phones with android 7 I usually get a nullpointer-exception on my Samsung S7 with Android 8.
The nullpointer-exception occurs when I try to access any UI-elements of the fragment within this function call!
I already checked that the fragment instances are valid, and they are ok. They are fully initialized and added on the onCreate of the host.
Whenever I trigger the function from inside the fragment it is ok, but not if I call the same function from the context menu of the hosting activity!
At first it looks like a timing problem, because sometimes it works, although relativ seldom.
What is the reason of this behaviour and how can I get over this strange error?
Thanks
Andreas
public class EpaperFragmentHost extends AppCompatActivity
{
private CustomViewPager mViewPager;
private Toolbar toolbar;
private EpaperPicture_Fragment EpaperPictureFrag;
private int Picture_Fragment_Position = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
setContentView(R.layout.activity_connectfragmenthost);
toolbar = findViewById(R.id.toolbar);
toolbar.setTitle( String.format( Locale.GERMAN,
getString(R.string.Connectingto_STRING) , mDeviceName) );
setSupportActionBar(toolbar);
mSectionsPagerAdapter = new Connection_fragment_adapter(
getSupportFragmentManager() );
EpaperPictureFrag = EpaperPicture_Fragment.newInstance( );
mSectionsPagerAdapter.setFragment( Picture_Fragment_Position,
EpaperPictureFrag );
mViewPager = findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.epapermenu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch(id){
case R.id.menuitem_savepicture:
// This call will fail on some phones, but works on others!
// And not because EpaperPictureFrag would be null, but the
// myDrawView inside this instance is null!
EpaperPictureFrag.takeScreenshot( true);
break;
default:
break;
}
boolean result = super.onOptionsItemSelected(item);
return result;
}
}
and this is the fragment:
public class EpaperPicture_Fragment extends Fragment
{
public DrawView myDrawView;
public EpaperPicture_Fragment() {
// Required empty public constructor
}
public static EpaperPicture_Fragment newInstance( ) {
EpaperPicture_Fragment fragment = new EpaperPicture_Fragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_epaper_picture, container,
false);
btn_Clear = v.findViewById(R.id.clear_btn);
btn_addText = v.findViewById(R.id.addtext_btn);
btn_Transmit = v.findViewById(R.id.transmit_btn);
myDrawView = v.findViewById(R.id.epaper);
btn_Clear.setOnClickListener( this );
btn_addText.setOnClickListener(this);
btn_Transmit.setOnClickListener( this );
return v;
}
#Override
public void onClick(View v) {
switch( v.getId() ){
case R.id.transmit_btn:
// This call works!
takeScreenshot( true );
break;
default:
break;
}
}
public File takeScreenshot(boolean showToast) {
// THIS IS THE PROBLEMATIC SECTION!
// Why can myDrawView be null, if the fragment exists?
myDrawView.setDrawingCacheEnabled(true);
Bitmap cachedBitmap = myDrawView.getDrawingCache();
Bitmap copyBitmap = cachedBitmap.copy(Bitmap.Config.RGB_565, true);
myDrawView.destroyDrawingCache();
// ...
}
}
Ok, the solution is:
I changed the check for storage access in the base-class to a new mode.
And this check caused each activity which was inherited by the baseclass to re-create after checking the access rights!
I found it by generating all overwrite methods of the base class and made a log-output in each. It was a terrible destroy and create-sequence.
Unfortunately I changed my test-phone around the same time...
I search everywhere and for the solution but not find it, I need some help.
I have an app that has Two activity's, Activity A and Activity B, but B have fragments, the first fragment from B, have an important data that I don't want to lose when the user press back when going to Activity A.
My problem is this every time I'm back to Activity A and go to B, my Data go empty because android clear it, so I made some search and changes on the code and still not find the solution. Now my code :
ACTIVITY A
fbReceive.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, OmniActivity.class));
}
});
I call B from this line and when they go to B this is the code :
ACTIVITY B
public class OmniActivity extends BaseActivity {
private View parent_view;
private TabLayout tab_layout;
FragmentOmni fragmentOmni = new FragmentOmni();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_omni_om);
parent_view = findViewById(R.id.container);
Tools.setSystemBarColor(this, R.color.new_purple_O200);
openFragment(fragmentOmni);
initToolbar();
initComponent();
}
public void openFragment(final Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.containerView, fragment, fragment.getTag());
transaction.addToBackStack(null);
transaction.commit();
}
#Override
public void onBackPressed() {
Intent intent = new Intent(this, MainActivity.class);
startActivityForResult(intent, 1);
}
private void initToolbar() {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("Voltar");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.getNavigationIcon().setColorFilter(getResources().getColor(android.R.color.white), PorterDuff.Mode.SRC_ATOP);
toolbar.setNavigationOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
Intent intent = new Intent(OmniActivity.this, MainActivity.class);
startActivityForResult(intent, 1);
}
});
}
And when the application executes OpenFragment() they go to this code from Fragment :
FRAGMENT A
public class FragmentOmni extends Fragment {
RecyclerView recyclerView;
MDOmniturn controller;
List<HashMap<String, String>> listproduct;
private ArrayList<Product> producttypelist;
Product tpobjproduct;
private ActionMode actionMode;
private ActionModeCallback actionModeCallback;
private ListProductAdapter lpAdapter;
private NestedScrollView nested_scroll_view;
private ImageButton bt_toggle_input;
private Button bt_hide_input;
private View lyt_expand_input;
EditText edOmni, edMani,edEan ;
LinearLayout layoutNoResult;
Handler time;
TextWatcher textexample;
private ProgressBar progressBarProduct;
LinearLayout linearLayout;
public FragmentOmni() {
}
public static FragmentOmni newInstance() {
FragmentOmni fragment = new FragmentOmni();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(savedInstanceState != null){
producttypelist = savedInstanceState.getParcelableArrayList("list");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_omni, container, false);
return root;
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putParcelableArrayList("list", producttypelist);
super.onSaveInstanceState(outState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
if (savedInstanceState != null) {
producttypelist = savedInstanceState.getParcelableArrayList("list");
}
initexpand(view);
linearLayout = (LinearLayout) view.findViewById(R.id.container);
edOmni = (EditText) view.findViewById(R.id.edOmni);
edMani = (EditText) view.findViewById(R.id.edBManifesto);
edEan = (EditText) view.findViewById(R.id.edEan);
progressBarProduct = (ProgressBar) view.findViewById(R.id.progressBarProduct);
layoutNoResult = (LinearLayout) view.findViewById(R.id.layoutNoResult);
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.addItemDecoration(new LineItemDecoration(getActivity(), LinearLayout.VERTICAL));
recyclerView.setHasFixedSize(true);
controller = new MDOmniturn(getActivity());
producttypelist = new ArrayList<>();
listproduct = new ArrayList<>();
addListenerTextChange(edOmni);
//set data and list adapter
lpAdapter = new ListProductAdapter(getActivity(), producttypelist);
recyclerView.setAdapter(lpAdapter);
lpAdapter.setOnClickListener(new ListProductAdapter.OnClickListener() {
#Override
public void onItemClick(View view, Product obj, int pos) {
if (lpAdapter.getSelectedItemCount() > 0) {
enableActionMode(pos);
} else {
// read the inbox which removes bold from the row
Product product = lpAdapter.getItem(pos);
Toast.makeText(getActivity(), "Read: " + product.prd_description, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onItemLongClick(View view, Product obj, int pos) {
enableActionMode(pos);
}
});
actionModeCallback = new ActionModeCallback();
}
The savedInstanceState from FRAGMENT A always go NULL, what i'm doing wrong?
Replace your code to the following order
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList("list", producttypelist);
}
It might be possible you are expecting data during the wrong state too.
For example, the savedInstanceState will always be null the first time an Activity is started which also points to your fragment, but may be non-null if an Activity is destroyed during rotation, because onCreate is called each time activity starts or restarts.
This line transaction.addToBackStack(null); is unnecessary. You can save the fragment state on its onStop() and onPause() and restore onResume() and onCreate().
You can remove the onBackPressed() in Activity B now
Alternatively, you can use Shared Preferences. When exiting the application, (onBackPressed, onPause ...) save the item you want. For Example the high score of a game.
activity.getSharedPreferences(getString(R.string.app_name),
Context.MODE_PRIVATE).edit().putInt("score", highScore).apply();
And retrieving the score would be:
int value = activity.getSharedPreferences(getString(R.string.app_name),
Context.MODE_PRIVATE).getInt("score", 0);
I have two activity namely MainActivity.java and Settings.java and others are fragments, MainActivity is the fragment_container, every fragment is attached here. Settings activity has the settings of changing language. MainActivity contains three buttons and if I click on the button next fragment in a same container displays listview.
If I change the language then if I come back to MainActivity from settings activity and then click on button the listview is still displaying English language. If I pressed back and again click on button then finally language are changed. Although the language aren't change in menu(onOptionsCreateMenu). I saved those settings in the sharedPreferences.
Now, after I exit my app and again come back then again same thing, if I click the button for the first time the language are in English if I come back to fragment and again click on button it changes language. What might be I missing? I searched related question in Stack Overflow but these aren't helpful. Below is my code:
MainActivity.java (This holds all Fragments)
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
ImageButton img_boy, img_girl, img_dog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
img_boy = (ImageButton) findViewById(R.id.img_boy);
img_boy.setOnClickListener(this);
img_girl = (ImageButton) findViewById(R.id.img_girl);
img_girl.setOnClickListener(this);
img_dog = (ImageButton) findViewById(R.id.img_dog);
img_dog.setOnClickListener(this);
Boolean isFirstRun = getSharedPreferences("Preference", MODE_PRIVATE).getBoolean("isFirstRun", true);
if (isFirstRun) {
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.Dark_theme);
builder.setTitle(R.string.chooselanguage).setItems(R.array.language, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
switch (i) {
case 1:
SharedPreferences ensharedPreferences = getSharedPreferences("selectedLanguage", Context.MODE_PRIVATE);
SharedPreferences.Editor eneditor = ensharedPreferences.edit();
eneditor.putString("language", "en");
eneditor.commit();
case 2:
SharedPreferences npsharedPrefrences = getSharedPreferences("selectedLanguage", Context.MODE_PRIVATE);
SharedPreferences.Editor npeditor = npsharedPrefrences.edit();
npeditor.putString("language", "ne");
npeditor.commit();
break;
}
}
}).setCancelable(false).create().show();
getSharedPreferences("Preference", MODE_PRIVATE).edit().putBoolean("isFirstRun", false).commit();
}
}
public void onBackPressed() {
CallForBackButton();
}
private void CallForBackButton() {
int count = getFragmentManager().getBackStackEntryCount();
switch (count) {
case 0:
QuitDialog();
break;
default:
getFragmentManager().popBackStack();
break;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.settings:
startActivity(new Intent(MainActivity.this, Settings.class));
break;
case android.R.id.home:
CallForBackButton();
break;
case R.id.exit:
QuitDialog();
}
return true;
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.img_boy:
Recycler rc = new Recycler();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_container, rc);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
// other case
}
}
Settings.java
public class Settings extends AppCompatActivity {
public static final String DEFAULT = "N/A";
Switch aSwitch, aSwitch2;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings);
aSwitch = (Switch) findViewById(R.id.swic);
aSwitch2 = (Switch) findViewById(R.id.swic2);
SharedPreferences sharedPreferences = getSharedPreferences("selectedLanguage", Context.MODE_PRIVATE);
String s1 = sharedPreferences.getString("language", DEFAULT);
if (s1.matches("ne")) {
aSwitch.setChecked(true);
} else {
aSwitch.setChecked(false);
}
aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (aSwitch.isChecked()) {
SharedPreferences npsharedPreferences = getSharedPreferences("selectedLanguage", Context.MODE_PRIVATE);
SharedPreferences.Editor npeditor = npsharedPreferences.edit();
npeditor.putString("language","ne");
npeditor.commit();
aSwitch.setChecked(true);
Toast.makeText(Settings.this, "Nepali Language Selected", Toast.LENGTH_LONG).show();
} else {
SharedPreferences ensharedPreferences = getSharedPreferences("selectedLanguage", Context.MODE_PRIVATE);
SharedPreferences.Editor eneditor = ensharedPreferences.edit();
eneditor.putString("language","en");
eneditor.commit();
Toast.makeText(Settings.this, "English Language Selected", Toast.LENGTH_LONG).show();
aSwitch.setChecked(false);
}
}
});
}
}
Recycler.java (This is RecyclerView where I put text to display)
public class Recycler extends Fragment {
private List<Name> names;
RecyclerView rv;
String[] nameCollection;
public static final String DEFAULT = "N/A";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.recyclerview, container, false);
rv = (RecyclerView) view.findViewById(R.id.rv);
nameCollection = getActivity().getResources().getStringArray(R.array.babies_names);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
rv.setHasFixedSize(true);
initializeData();
initializeAdapter();
return view;
}
private void initializeAdapter() {
rvadapter adapter = new rvadapter(names);
rv.setAdapter(adapter);
}
public void initializeData() {
names = new ArrayList<>();
SharedPreferences sharedPreferences = getActivity().getSharedPreferences("selectedLanguage", Context.MODE_PRIVATE);
String pine= sharedPreferences.getString("language", DEFAULT);
String languageToLoad=pine;
Locale locale=new Locale(languageToLoad);//Set Selected Locale
Locale.setDefault(locale);//set new locale as default
Configuration config = new Configuration();//get Configuration
config.locale = locale;//set config locale as selected locale
getActivity().getResources().updateConfiguration(config, getActivity().getResources().getDisplayMetrics());
for (int i = 0; i < nameCollection.length; i++) {
names.add(new Name(nameCollection[i]));
}
}
}
I just need to fix the language as selected by user.
One more thing, if I exit the app but not close from recent apps then, if I again go back to my app then everything works fine, languages also changes on menu(onOptionMenu). I think the quick fix for this is saving it in savedInstanceState but I am not sure and I don't know how to use that in my case.
I call Locale under MainActivity.java on onStart() callback instead of calling in instalizeData() on recyclerView and now everything working fine :D
I have my main activity actionbaractivity One where you can screenslide through some fragmets, on each fragment you have an imageView and a ListView where you can click any item and the image will change. Also in the menu options you have a button where you change to an almost exact activity: actiobbaractivity Two which also have this button to change to activity One
What I'm able to do is to keep the image when sliding the fragments, but unable to keep the fragments state's through the change of activities.
For example
I'm in activity One on fragment 3 with the image: "something". I click on the button to change to activity Two, I do things here and then, I click on the button to change to activity One and I want to see my fragment 3 with the image: "something" and not the default fragment 1 and default image
Im using ActionBarActivity, FragmentStatePagerAdapter and Fragment for each activity
Thanks for the help
According to the Activity and Fragment lifecycles (http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle and http://developer.android.com/guide/components/fragments.html#Lifecycle), the most reliable way of persisting states between activity/fragment changes is to use the default API for saving and restoring states:
When the activity/fragment is being dismissed (either because of a configuration change such as screen rotation or because the user requested to go to another activity/fragment), you can save its state in a Bundle object. When it is being created, you can restore its saved state, thus recreating a new instance exactly like the one the user left - so the user feels nothing has changed. This does not depend on the specific subclass of activity/fragment you are using.
I have implemented something like what you want: in my case, a fragment containing a menu with buttons that would each lead the user to another fragment containing a submenu with a "back" button. So if the user went from menu to submenu 1, then back to menu, then to submenu 2, then back to menu and finally again to submenu 1, I wanted that submenu 1 to appear just like the user has left it in the first time.
For that I have created:
1) an interface defining my submenu types, implemented by my activities so they could change between my submenus
2) a master generic class, which all my submenus would extend, that had a Bundle object to store their state
3) in my activities, I had an array of Bundle capable of storing one instance of each of my submenus (because I am only interested in restoring the last state, so I don't need more than one)
The interface (item 1):
public interface SubmenusManager {
public static enum Submenus {
ROOTMENU,
SUBMENU1,
SUBMENU2;
private static final int size = Submenus.values().length;
public static int size() {
return size;
}
public static int getId(Submenus test) {
switch(test) {
case SUBMENU1:
return 1;
case SUBMENU2:
return 2;
case ROOTMENU:
default:
return 0;
}
}
}
public void cloneCurrentSubmenuState(Parcelable toOverwrite);
public Bundle getLastStoredSubmenuState(Submenus submenu);
public void setCurrentSubmenuTo(Submenus submenu);
}
The generic class (item 2):
public class MenuFragment extends Fragment {
private Bundle menuData = new Bundle();
public static String RESTORE_MAIN_OBJECT = "restore_main";
public Bundle getMenuData() {
return menuData;
}
public Bundle cloneMenuData() {
return new Bundle(menuData);
}
public void setMenuData(Bundle menuData) {
this.menuData = menuData;
}
}
One of the activities (item 3):
public class ExampleAct extends FragmentActivity implements SubmenusManager {
/**
* instance variables
*/
private MenuFragment mMenu;
private Bundle [] menuData; // the Array of Bundles!
private static final String CONTAINER = "parcelable_container";
private static final String SUBMENU = "saved_submenu";
private Submenus curSubmenu = Submenus.ROOTMENU; // the default state is the ROOTMENU
private boolean restoreLastSavedState = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) { // first time creating this activity
menuData = new Bundle[Submenus.size()];
} else { // this activity has a saved state from before
// restore all the data from all the submenus
menuData = (Bundle[]) savedInstanceState.getParcelableArray(CONTAINER);
// restore the info about which is the current active submenu
curSubmenu = (Submenus) savedInstanceState.getSerializable(SUBMENU);
}
buildMenuFragment(true);
//(...) stuff
}
private void buildMenuFragment(boolean restoreState) {
// (re)builds fragment inside menu.
// restoreState flags whether activity should look for
// saved state data and restore it
restoreLastSavedState = restoreState;
switch(curSubmenu) {
// Eclipse warns you about which are the constants in your enum
case ROOTMENU:
mMenu = new FragmentRootMenu();
break;
case SUBMENU1:
mMenu = new FragmentSubmenu1();
break;
case SUBMENU2:
mMenu = new FragmentSubmenu2();
break;
}
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.menu_frame, mMenu)
.commit();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(SUBMENU, curSubmenu);
cloneCurrentSubmenuState(mMenu.getMenuData().
getParcelable(MenuFragment.RESTORE_MAIN_OBJECT));
outState.putParcelableArray(CONTAINER, menuData);
// (...) stuff
}
#Override
public void cloneCurrentSubmenuState(Parcelable toOverwrite) {
if (menuData == null) menuData = new Bundle[Submenus.size()];
if (toOverwrite != null)
mMenu.getMenuData().putParcelable(MenuFragment.RESTORE_MAIN_OBJECT, toOverwrite);
menuData[Submenus.getId(curSubmenu)] = mMenu.cloneMenuData();
}
#Override
public Bundle getLastStoredSubmenuState(Submenus forThisSubmenu) {
return
(menuData == null || !restoreLastSavedState) ? new Bundle() : menuData[Submenus.getId(forThisSubmenu)];
}
#Override
public void setCurrentSubmenuTo(Submenus toThisSubmenu) {
if (mMenu != null) {
cloneCurrentSubmenuState(mMenu.getMenuData().
getParcelable(MenuFragment.RESTORE_MAIN_OBJECT));
}
curSubmenu = toThisSubmenu;
buildMenuFragment(true);
}
One of the submenus (extension of item 2):
public class FragmentSubmenu1 extends MenuFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_submenu1, null);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
init();
}
public void init() {
// (...) stuff
MyParcelableObject tmp = null; // MyParcelableObject is a class
// that implements Parcelable and stores
// relevant info to rebuild this menu
// from a saved state
SubmenusManager m = (SubmenusManager) getActivity(); // remember activity implements SubmenusManager
Bundle bnd = m.getLastStoredSubmenuState(SubmenusManager.Submenus.SUBMENU1);
if (bnd != null) tmp = bnd.getParcelable(MenuFragment.RESTORE_MAIN_OBJECT);
if (tmp == null) {
tmp = new MyParcelableObject();
tmp.buildFromScratch(); // initializes with default data
}
// back button
Button backToMainMenu = (Button) getView().findViewById(R.id.submenu1_back);
backToMainMenu.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
((SubmenusManager) getActivity()).
setCurrentSubmenuTo(SubmenusManager.Submenus.ROOTMENU);
}
});
// (...) stuff
}
}
The Root menu (extension of item 2):
public class FragmentRootMenu extends MenuFragment {
View myView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myView = inflater.inflate(R.layout.fragment_rootmenu, null);
return myView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
init();
}
public void init() {
Button btnSubmenu1 = (Button) myView.findViewById(R.id.btn_call_submenu1);
btnSubmenu1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
((SubmenusManager) getActivity()).
setCurrentSubmenuTo(SubmenusManager.Submenus.SUBMENU1);
}
});
Button btnSubmenu2 = (Button) myView.findViewById(R.id.btn_call_submenu2);
btnSubmenu2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
((SubmenusManager) getActivity()).
setCurrentSubmenuTo(SubmenusManager.Submenus.SUBMENU2);
}
});
}
}
For that to work between activities, all you need to do is pass that object that stores the last state of all fragments (in my case, that would be Bundle [] menuData) to the activity that is being called through its Intent; you would recover it the same way as my ExampleAct did in its onCreate(). You could also wrap that Bundle [] inside a custom Parcelable object (very similar to my example MyParcelableObject; inside that one I had stuff like HashMap) if using an array is a problem.
Here how to pass a Parcelable between activities:
How to send an object from one Android Activity to another using Intents?