【问题标题】:Restoring State of Spinners and Their Adapters恢复微调器及其适配器的状态
【发布时间】:2017-12-28 19:56:40
【问题描述】:

我在尝试在我的应用程序中恢复 Android Spinner 的状态时遇到问题。目前,我的 Activity 的 ListView 标头中有多个 Spinner,它们相互依赖,因为选择一个 Spinner 会为后续 Spinner 加载数据。

我遇到的问题是,当我在 Spinners 上手动设置选择时,恢复状态似乎不起作用。我已经尝试过 onRestoreInstanceState 和 onResume。在查看 LogCat 输出时,似乎设置选择是异步的。当我必须等待一个被选中才能填充并设置另一个 Spinner 时,如何可靠地恢复这些 Spinner 的状态?

编辑:添加代码

Activity 的 onCreate():

mSecondSpinner = mMyListHeader.findViewById(R.id.second_spinner);
mSecondSpinnerArrayAdapter = new SecondArrayAdapter(MyActivity.this, R.layout.second_spinner_item, new ArrayList<MySecondDto>());
mSecondSpinner.setAdapter(mSecondSpinnerArrayAdapter);
mSecondSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

   @Override
   public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

      MySecondDto selectedMySecondDto = (MySecondDto) parent.getItemAtPosition(position);
      List<MyThirdDto> myThirdDtos = selectedMySecondDto.getMyThirdDtos();

      // Load third spinner with dtos....
   }

   @Override
   public void onNothingSelected(AdapterView<?> parent) {}}
);

mFirstSpinner = mMyListHeader.findViewById(R.id.first_spinner);
mFirstSpinnerAdapter= new FirstArrayAdapter(MyActivity.this, R.layout.first_spinner, mResponse.getAllDtos());
mFirstSpinner.setAdapter(mFirstSpinnerArrayAdapter);
mFirstSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

   @Override
   public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

      mSecondSpinner.setAdapter(null);

      MyFirstDto selectedMyFirstDto = (MyFirstDto ) parent.getItemAtPosition(position);
      List<MySecondDto> mySecondDtos = selectedMyFirstDto .getMySecondDtos();

      mSecondSpinnerArrayAdapter.clearAndReplaceAll(mySecondDtos);
      mSecondSpinner.setAdapter(mSecondSpinnerArrayAdapter);

      // If there is only one second dto, disable the spinner
      if (mySecondDtos== null || mySecondDtos.size() <= 1)
      {
          disableSpinner(mSecondSpinner);
      }
      else
      {
          // Enable second spinner, select the hint element
          enableSpinner(mSecondSpinner);
          mSecondSpinner.setSelection(mSecondSpinnerArrayAdapter .getHintIndex());
      }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {}
});

Activity的onRestoreInstanceState():

 mFirstSpinner.setSelection(mFirstAdapterPosition);
 mFirstSpinnerArrayAdapter.notifyDataSetChanged();

 mSecondSpinner.setSelection(mSecondAdapterPosition);
 mSecondSpinnerArrayAdapter.notifyDataSetChanged();

【问题讨论】:

  • 你试过了吗.... BaseAdapter 适配器 = (BaseAdapter) yourSpinner.getAdapter(); adapter.notifyDataSetChanged();
  • 能否提供您的示例代码sn-p
  • @NikhilLotke 用一些代码更新了帖子。
  • 您在哪里存储 mFirst/SecondAdapterPosition?它必须在 onSaveInstanceState Bundle 中

标签: android spinner android-arrayadapter onsaveinstancestate onrestoreinstancestate


【解决方案1】:

你试过了吗

mySpinner.post(new Runnable() { @Override public void run() { mySpinner.setSelection(position); } });

【讨论】:

  • 嗨。我不确定你的意思。这会在 onRestoreInstanceState 中完成吗,我将如何“等待”直到在第一个微调器中完成选择,然后在第二个中执行相同操作?
【解决方案2】:

这可能对你有用。 某处可能有错误,所以要小心。 我和你有类似的情况,但我有 3 个微调器,它们的填充取决于前一个的选择。

这个想法是将 Spinners 的索引/位置存储在 IndexVariables 中。 这些变量的默认值为 -1。

在 onSaveInstanceState 中存储当前值,

恢复 onActivityCreated 中的值。

在 onItemSelected 检查选中的 Item = null,检查是否设置了 IndexVariable(即 !-= -1)

如果是这样使用它来设置 Spinner 然后将 IndexVariable 设置回 -1;

这是课程

(我使用了来自 How to make an Android Spinner with initial text "Select One" 的 NothingSelectedSpinnerAdapter。 不是很重要,只是向我得到该代码的男孩/女孩大声喊叫。)

public class SpinnerTestFragment  extends Fragment {

private MainActivity activity;

private static final String SELECTED_THEME_IDX_STORAGE_KEY = "mSelectedTheme_IDX_StorageKey";
private static final String SELECTED_AIM_IDX_STORAGE_KEY = "mSelectedAim_IDX_StorageKey";
private static final String SELECTED_GOAL_IDX_STORAGE_KEY = "mSelectedGoal_IDX_StorageKey";

private static String TAG = "SpinnerTestFragment";

private Spinner spnrThemes;
private Spinner spnrAims;
private Spinner spnrGoals;

private String mSelectedTheme;
private String mSelectedAim;
private String mSelectedGoal;

private int mSelectedAimIdx = -1;
private int mSelectedThemeIdx = -1;
private int mSelectedGoalIdx = -1;


//----------------------------------------------------------------------------------------//


public SpinnerTestFragment() {
}//ctor

//----------------------------------------------------------------------------------------//

@Override
public View onCreateView(LayoutInflater inflater,
                         ViewGroup container,
                         Bundle savedInstanceState) {
    Log.d(TAG, "onCreateView");

    activity = (MainActivity) getActivity();


    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_photo, container, false);


    spnrThemes = view.findViewById(R.id.spnrThemes);
    spnrAims = view.findViewById(R.id.spnrAims);
    spnrGoals = view.findViewById(R.id.spnrGoals);


    setSpinner(spnrThemes, "Select Theme", ThemesAimsGoals.getThemes());

    spnrThemes.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            Object selectedItem = parent.getItemAtPosition(position);

            if (selectedItem != null) {
                mSelectedTheme = selectedItem.toString();
                setSpinner(spnrAims, "Select Aim", ThemesAimsGoals.getAims(mSelectedTheme));

            } else if(mSelectedThemeIdx != -1){
                selectedItem = parent.getItemAtPosition(mSelectedThemeIdx);
                mSelectedTheme = selectedItem.toString();
                setSpinner(spnrAims, "Select Aim", ThemesAimsGoals.getAims(mSelectedTheme));
                parent.setSelection(mSelectedThemeIdx);
                mSelectedThemeIdx = -1;
            }//Else
        }//onItemSelected

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });


    spnrAims.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            Object selectedItem = parent.getItemAtPosition(position);

            if (selectedItem != null) {
                mSelectedAim = selectedItem.toString();
                setSpinner(spnrGoals, "Select Goal", ThemesAimsGoals.getGoals(mSelectedTheme, mSelectedAim));

            } else if(mSelectedAimIdx != -1){
                selectedItem = parent.getItemAtPosition(mSelectedAimIdx);
                mSelectedAim = selectedItem.toString();
                setSpinner(spnrGoals, "Select Goal", ThemesAimsGoals.getGoals(mSelectedTheme, mSelectedAim));
                parent.setSelection(mSelectedAimIdx);
                mSelectedAimIdx = -1;
            }//Else
        }//onItemSelected

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });

    spnrGoals.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            Object selectedItem = parent.getItemAtPosition(position);
            if (selectedItem != null) {
                mSelectedGoal = selectedItem.toString();

            }else if(mSelectedGoalIdx != -1){
                selectedItem = parent.getItemAtPosition(mSelectedGoalIdx);
                mSelectedGoal = selectedItem.toString();
                parent.setSelection(mSelectedGoalIdx);
                mSelectedGoalIdx = -1;
            }//Else
        }//onItemSelected

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });

    return view;
}//onCreateView

//----------------------------------------------------------------------------------------//

/**
 * Populate Spinner
 * @param spnr Spinner to populate
 * @param prompt What to show at the start
 * @param array Items in the spinner
 */
private void setSpinner(Spinner spnr, String prompt, String[] array) {
    spnr.setPrompt(prompt);
    ArrayAdapter<CharSequence> adapter = new ArrayAdapter(activity, android.R.layout.simple_spinner_item, array);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spnr.setAdapter(
            new NothingSelectedSpinnerAdapter(
                    adapter,
                    R.layout.contact_spinner_row_nothing_selected,
                    activity,
                    prompt));
}//setSpinner

//----------------------------------------------------------------------------------------//

/**
 * Some lifecycle callbacks so that the image can survive orientation chang
 *
 * @param outState current state of fragment
 */
@Override
public void onSaveInstanceState(Bundle outState) {
    Log.d(TAG, "onSaveInstanceState");
    super.onSaveInstanceState(outState);

    outState.putInt(SELECTED_THEME_IDX_STORAGE_KEY, spnrThemes.getSelectedItemPosition());
    outState.putInt(SELECTED_AIM_IDX_STORAGE_KEY, spnrAims.getSelectedItemPosition());
    outState.putInt(SELECTED_GOAL_IDX_STORAGE_KEY, spnrGoals.getSelectedItemPosition());

}//onSaveInstanceState

//----------------------------------------------------------------------------------------//

/**
 * Rebuilds the Activity/Fragment in the image of the last one.
 *
 * @param savedInstanceState Info from last session or rotation
 */
@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    Log.d(TAG, "onActivityCreated");

    if (savedInstanceState == null)
        return;

    mSelectedThemeIdx = savedInstanceState.getInt(SELECTED_THEME_IDX_STORAGE_KEY);
    mSelectedAimIdx = savedInstanceState.getInt(SELECTED_AIM_IDX_STORAGE_KEY);
    mSelectedGoalIdx = savedInstanceState.getInt(SELECTED_GOAL_IDX_STORAGE_KEY);


}//onActivityCreated

}//Cls

【讨论】:

  • 感谢 Shanie,但我正在尝试重新创建它,但从我的日志语句中,它似乎在调用 onActivityCreated 之前调用了 onCreateView,所以我不确定这将如何工作。 Spinner 在尝试恢复值之前已经初始化。
  • @JPM 我改变了主意。真正的答案在这里stackoverflow.com/questions/27745948/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多