У меня возникли проблемы с сохранением программно созданных представлений при выполнении фрагмента

#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