#android #android-fragments #sharedpreferences #android-view
#Android #android-фрагменты #sharedpreferences #android-просмотр
Вопрос:
Я настроил его так, что созданные пользователем представления сохраняются через общие настройки. Информация переносится нормально, однако, когда я пытаюсь воссоздать эти представления с общей информацией о предпочтениях, приложение выходит из строя. Проблема, похоже, в том, что фрагмент загружается не полностью, когда вызывается моя функция для воссоздания представлений. Однако я не уверен, где я должен вызывать настройки загрузки, чтобы убедиться, что все представления были увеличены. Я пробовал onResume (), OnStart () и несколько других возможностей, и все они приводят к одной и той же проблеме.
Мои фрагменты настроены следующим образом:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dice);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each of the two primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_dice, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_dice, container, false);
return rootView;
}
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new fragment_dice();
break;
case 1:
fragment = new fragment_history();
break;
}
return fragment;
}
@Override
public int getCount() {
// Show 2 total pages.
return 2;
}
}
Файл Java с фрагментом Dice:
public class fragment_dice extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable
ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_dice, container, false);
return v;
}
}
История Java-файла:
public class fragment_history extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_history, container, false);
return v;
}
}
Функции общих настроек:
public void onPause() {
super.onPause();
SharedPreferences sp = getSharedPreferences("preferences", Context.MODE_PRIVATE);
SharedPreferences.Editor spEditor = sp.edit();
Log.d("test", "Save Size " createdDiceNames.size());
spEditor.putInt("Die_size", createdDiceNames.size());
for (int i = 0; i < createdDiceNames.size(); i ) {
spEditor.remove("Die_" i);
spEditor.putString("Die_" i, createdDiceNames.get(i));
}
spEditor.commit();
}
public void loadPreferences() {
SharedPreferences mSp = getSharedPreferences("preferences", Context.MODE_PRIVATE);
SharedPreferences.Editor spEditor = mSp.edit();
createdDiceNames.clear();
int size = mSp.getInt("Die_size", 0);
Log.d("test", "Load Size " size);
for (int i = 0; i < size; i ) {
customDiceName = mSp.getString("Die_" i, "").replaceAll(". _","");
for (int b = 0; b < createdDiceNames.size(); b ) {
Log.d("test", "Array Value " createdDiceNames.get(b));
}
Log.d("test", "Dice Name " customDiceName);
//This function is where the views are re-inflated and this is where the error occurs because the table layout has not yet loaded in the fragment
createCustomDice();
}
}
Я попытался вызвать функцию настройки загрузки с помощью кнопки, как только приложение запустилось, чтобы убедиться, что оно работает должным образом, и это сработало. Мой вопрос в том, куда поместить функцию, чтобы она загружалась только после загрузки представлений фрагментов и не приводила к сбою.
Ответ №1:
Если вы настаиваете на использовании общих настроек, нам нужно просмотреть ваш logcat.
В любом случае, я думаю, вы, возможно, захотите использовать базу данных. Я предлагаю вам использовать любую схему без (например, ObjectBox), но вы должны использовать любой тип. Общие настройки используются для объектов типа ключ-значение (например, preferences), но не для динамически изменяющихся объектов.
Комментарии:
1. Даже если бы я переключился на базу данных, не возникло бы у меня той же проблемы с загрузкой этих данных до загрузки фрагмента, или базы данных просто работают иначе, чем общие настройки таким образом?
2. Вроде как да. При использовании SQLite вы определяете столбцы, и каждая строка может иметь разное значение. Затем вы используете курсор и просматриваете все ячейки. С другой стороны, базы данных без схемы могут быть определены с использованием объектов, где у вас могут быть атрибуты, которые вы затем, возможно, захотите объединить с viewmodel. Взгляните сюда: docs.objectbox.io/entity-annotations