Android开发如何避免使用片段和选项菜单保存上下文
在android应用程序中,我有一个包含片段的活动 该片段具有一个“updateScore”函数,该函数使用当前分数更新UI 此函数从片段中调用,也应从活动中的选项菜单中调用 如果我将上下文保存为片段中的静态变量,这是可以实现的,但这是一种糟糕的做法。那么我应该怎么做呢 主要活动:Android开发如何避免使用片段和选项菜单保存上下文,android,android-fragments,android-context,android-menu,Android,Android Fragments,Android Context,Android Menu,在android应用程序中,我有一个包含片段的活动 该片段具有一个“updateScore”函数,该函数使用当前分数更新UI 此函数从片段中调用,也应从活动中的选项菜单中调用 如果我将上下文保存为片段中的静态变量,这是可以实现的,但这是一种糟糕的做法。那么我应该怎么做呢 主要活动: public class MainActivity extends AppCompatActivity { public static int totalCorrect; @Override
public class MainActivity extends AppCompatActivity {
public static int totalCorrect;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
ExerciseFragment exerciseFragment = new ExerciseFragment();
fragmentTransaction.add(R.id.fragment_container, exerciseFragment);
fragmentTransaction.commit();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
int id = item.getItemId();
if (id == R.id.option_reset_score) {
totalCorrect = 0;
ExerciseFragment.updateScore();
}
}
}
练习片段:
public class ExerciseFragment extends Fragment {
private static View view; //bad practice
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_exercises, container, false);
ExerciseFragment.view = view;
updateScore();
return view;
}
public static void updateScore() {
TextView totalCorrectTextView = (TextView) view.findViewById(R.id.total_correct);
totalCorrectTextView.setText(MyApp.getAppContext().getString(R.string.correct) + ": " + String.valueOf(MainActivity.totalCorrect));
}
}
按以下方式更改您的练习片段:
public class ExerciseFragment extends Fragment {
private View mView;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.fragment_exercises, container, false);
updateScore();
return mView;
}
public void updateScore() {
TextView totalCorrectTextView = (TextView) mView.findViewById(R.id.total_correct);
totalCorrectTextView.setText(getActivity().getString(R.string.correct) + ": " + String.valueOf(MainActivity.totalCorrect));
}
}
在活动中,您可以通过其容器的ID找到当前片段:
ExerciseFragment exerciseFragment = (ExerciseFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_container);
然后你可以使用他的方法:
exerciseFragment.updateScore();
我认为视图或方法不需要是静态的
public class ExerciseFragment extends Fragment {
private View view;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_exercises, container, false);
ExerciseFragment.view = view;
updateScore();
return view;
}
public void updateScore() {
TextView totalCorrectTextView = (TextView) view.findViewById(R.id.total_correct);
totalCorrectTextView.setText(MyApp.getAppContext().getString(R.string.correct) + ": " + String.valueOf(MainActivity.totalCorrect));
}
}
你一定是在什么地方启动了碎片
public class MainActivity extends AppCompatActivity {
public static int totalCorrect;
public ExerciseFragment exerciseFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
exerciseFragment= new ExerciseFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (getFragmentManager().findFragmentById(R.id.fragment_container) != null)
fragmentManager.popBackStack();
fragmentTransaction.replace(R.id.fragment_container, currentFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
int id = item.getItemId();
if (id == R.id.option_reset_score) {
totalCorrect = 0;
exerciseFragment.updateScore();
return true;
}
return false;
}
}
这不是最好的做法。我建议你做的是:
- 创建一个接口,比如“ScoreUpdater”,方法是“updateScore”
- 使您的活动扩展此接口
- 将“updateScore”方法的逻辑从片段移动到活动中的此重写方法
- 在片段的“onAttach”方法上,检查片段所附加到的上下文是否是此ScoreUpdater接口的实例,并保存指向它的链接
@Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof ScoreUpdater) scoreUpdater = (ScoreUpdater)context; ... }
- 每当需要从片段中更新分数时,只需从片段中调用scoreUpdater.updateScore(),从活动中调用updateScore()
这是你的问题。您的片段可以提供自己的选项菜单项。您需要覆盖片段中的
onCreateOptionsMenu
和onOptionsItemSelected
,并在片段的一个设置生命周期方法中调用setHasOptionsMenu(true)
。请参阅。您是否正在MainActivity中加载练习片段???您是否知道使用接口?您可以通过创建片段的静态实例来调用该方法。请发布您的代码片段,说明如何在活动中加载片段??我添加了onCreate函数,在其中加载片段,但如果我不想静态保存视图,我需要将updateScore()改为updateScore(视图视图)。我编辑了答案。您的视图不需要是静态的。谢谢。静态exerciseFragment变量也不是一个好的实践,但它不必是静态的。
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof ScoreUpdater)
scoreUpdater = (ScoreUpdater)context;
...
}