【发布时间】:2022-01-19 05:49:25
【问题描述】:
背景
我遇到了一个涉及更新 Android 项目中的 Fragment 的问题。该应用程序为 D&D 玩家掷骰子。与 Java Math.random 方法相比,该项目使用来自 Random.Org 的 API 来提供更大的随机数生成熵。
该应用程序显示一个带有视图分页器的选项卡布局,它在三个选项卡之间切换 - 一个用于掷一个骰子,一个用于掷一组骰子,一个用于显示掷骰历史和日志信息。 Roll Die 位于位置 0,Roll Set 位于位置 1,History 位于位置 2。View Pager 使用 FragmentPagerAdapter。
History 包含两个 TextView,我使用它们来显示滚动结果和记录数据,以确保与 API 的连接顺利进行。数据通过两个接口从 RollDie 和 RollSet 片段传递到 Main Activity。然后接口方法将数据发送到 FragmentPagerAdapter,FragmentPagerAdapter 又通过 bundle 将两个 String ArrayLists 传递给 History 片段。
问题
我的问题是历史选项卡似乎仅在加载单个骰子选项卡后才更新。当我掷出一个骰子然后检查历史页面时,相关的 TextView 会按应有的方式显示。然而,当我掷出一组时,历史页面不会更新,直到我返回单个掷骰子选项卡。
对于这个问题的任何帮助将不胜感激。相关代码贴在下面。
API 代码可以在Github 上找到。我还遗漏了我编写的两个类,称为 Die 和 DieSet - 它们运行良好,我认为这已经足够长了。如果有人认为有帮助,我很乐意发布这些课程。
与 API 密钥相关的代码以及一些 IDE 生成的 cmets 已被省略。
主要活动
public class MainActivity extends AppCompatActivity implements DieRollFragment.RollFragmentListener, DieSetFragment.SetFragmentListener{
private static String[] key;
TabLayout tabLayout;
ViewPager viewPager;
PagerAdapter pagerAdapter;
protected void onStart() {
super.onStart();
userKeyDialog();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabLayout = findViewById(R.id.navTabs);
viewPager = findViewById(R.id.viewPager);
pagerAdapter = new PagerAdapter(getSupportFragmentManager(), BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, tabLayout.getTabCount());
viewPager.setAdapter(pagerAdapter);
tabLayout.setupWithViewPager(viewPager);
}
private void userKeyDialog(){
//OMITTED FOR PRIVACY REASONS
}
public static String getKey() {
//OMITTED FOR PRIVACY REASONS
}
//DieRollFragment Interface Methods
@Override
public void rollResultsUpdate(String input) {
pagerAdapter.setResults(input);
}
@Override
public void rollLogsUpdate(String input) {
pagerAdapter.setLogs(input);
}
//DieSetFragment Interface Methods
@Override
public void setResultsUpdate(String input) {
pagerAdapter.setResults(input);
}
@Override
public void setLogsUpdate(String input) {
pagerAdapter.setLogs(input);
}
}
FragmentPagerAdapter
public class PagerAdapter extends FragmentPagerAdapter {
int numOfTabs;
ArrayList<String> results;
ArrayList<String> logs;
public PagerAdapter(FragmentManager fm, int behavior, int numOfTabs) {
super(fm, behavior);
this.numOfTabs = numOfTabs;
results = new ArrayList<>();
logs = new ArrayList<>();
}
@NonNull
@Override
public Fragment getItem(int position) {
switch(position){
case(1):
return DieSetFragment.newInstance(getKey());
case(2):
return RollHistoryFragment.newInstance(results, logs);
case(0):
default:
return DieRollFragment.newInstance(getKey());
}
}
@Override
public CharSequence getPageTitle(int position){
String title;
switch(position){
case(1):
title = "Roll Set";
return title;
case(2):
title = "Results";
return title;
case(0):
default:
title = "Roll Die";
return title;
}
@Override
public int getCount() {
return 3;
}
public void setResults(String input) {
results.add(input);
}
public void setLogs(String input) {
logs.add(input);
}
}
RollHistoryFragment
public class RollHistoryFragment extends Fragment{
TextView results, logs;
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
ArrayList<String> inputResults, inputLogs;
Button clearLogs;
public RollHistoryFragment() {
// Required empty public constructor
}
public static RollHistoryFragment newInstance(ArrayList<String> inputResults, ArrayList<String> inputLogs) {
RollHistoryFragment fragment = new RollHistoryFragment();
Bundle args = new Bundle();
args.putStringArrayList(ARG_PARAM1, inputResults);
args.putStringArrayList(ARG_PARAM2, inputLogs);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
inputResults = getArguments().getStringArrayList(ARG_PARAM1);
inputLogs = getArguments().getStringArrayList(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_roll_history, container, false);
results = view.findViewById(textViewResults);
results.setMovementMethod(new ScrollingMovementMethod());
logs = view.findViewById(textViewLogs);
logs.setMovementMethod(new ScrollingMovementMethod());
clearLogs = view.findViewById(buttonClear);
clearLogs.setOnClickListener(view1 -> {
results.setText("");
logs.setText("");
});
updateResults(inputResults);
updateLogs(inputLogs);
return view;
}
public void updateResults(ArrayList<String> input){
for (String s : input) results.append(s+"\n");
}
public void updateLogs (ArrayList<String> input){
for (String s : input) logs.append(s+"\n");
}
}
DieRollFragment
public class DieRollFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private String key;
private RollFragmentListener listener;
public DieRollFragment() {
// Required empty public constructor
}
public static DieRollFragment newInstance(String key){
DieRollFragment fragment = new DieRollFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, key);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
key = getArguments().getString(ARG_PARAM1);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_die_roll, container, false);
ImageButton rollD4 = view.findViewById(R.id.rollD4);
ImageButton rollD6 = view.findViewById(R.id.rollD6);
ImageButton rollD8 = view.findViewById(R.id.rollD8);
ImageButton rollD10 = view.findViewById(R.id.rollD10);
ImageButton rollD12 = view.findViewById(R.id.rollD12);
ImageButton rollD20 = view.findViewById(R.id.rollD20);
ImageButton rollD100 = view.findViewById(R.id.rollD100);
rollD4.setOnClickListener(view1 -> {
Die d4 = new Die(4, key);
int result = d4.makeRoll();
showAlert(result);
listener.rollResultsUpdate("Roll = " + result);
listener.rollLogsUpdate(d4.getLog());
});
rollD6.setOnClickListener(view12 -> {
Die d6 = new Die(6, key);
int result = d6.makeRoll();
showAlert(result);
listener.rollResultsUpdate("Roll = " + result);
listener.rollLogsUpdate(d6.getLog());
});
rollD8.setOnClickListener(view13 -> {
Die d8 = new Die(8, key);
int result = d8.makeRoll();
showAlert(result);
listener.rollResultsUpdate("Roll = " + result);
listener.rollLogsUpdate(d8.getLog());
});
rollD10.setOnClickListener(view14 -> {
Die d10 = new Die(10, key);
int result = d10.makeRoll();
showAlert(result);
listener.rollResultsUpdate("Roll = " + result);
listener.rollLogsUpdate(d10.getLog());
});
rollD12.setOnClickListener(view15 -> {
Die d12 = new Die(12, key);
int result = d12.makeRoll();
showAlert(result);
listener.rollResultsUpdate("Roll = " + result);
listener.rollLogsUpdate(d12.getLog());
});
rollD20.setOnClickListener(view16 -> {
Die d20 = new Die(20, key);
int result = d20.makeRoll();
showAlert(result);
listener.rollResultsUpdate("Roll = " + result);
listener.rollLogsUpdate(d20.getLog());
});
rollD100.setOnClickListener(view17 -> {
Die d100 = new Die(100, key);
int result = d100.makeRoll();
showAlert(result);
listener.rollResultsUpdate("Roll = " + result);
listener.rollLogsUpdate(d100.getLog());
});
return view;
}
public interface RollFragmentListener{
void rollResultsUpdate(String input);
void rollLogsUpdate(String input);
}
private void showAlert(int result){
new AlertDialog.Builder(Objects.requireNonNull(getContext()))
.setTitle("You rolled a: ")
.setMessage(Integer.toString(result))
.show();
}
public void onAttach(@NonNull Context context) {
super.onAttach(context);
if(context instanceof RollFragmentListener){
listener = (RollFragmentListener) getContext();
} else throw new RuntimeException(context.toString() + " must implement RollFragmentListener");
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
}
DieSetFragment
public DieSetFragment() {
// Required empty public constructor
}
public static DieSetFragment newInstance(String key) {
DieSetFragment fragment = new DieSetFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, key);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_die_set, container, false);
assert container != null;
editNumD4 = view.findViewById(R.id.editNumD4);
editNumD6 = view.findViewById(R.id.editNumD6);
editNumD8 = view.findViewById(R.id.editNumD8);
editNumD10 = view.findViewById(R.id.editNumD10);
editNumD12 = view.findViewById(R.id.editNumD12);
editNumD20 = view.findViewById(R.id.editNumD20);
diceSetList = new ArrayList<>();
ImageButton buttonRollSet = view.findViewById(R.id.buttonRollSet);
buttonRollSet.setOnClickListener(view1 -> rollSet(mParam1));
return view;
}
public interface SetFragmentListener{
void setResultsUpdate(String input);
void setLogsUpdate(String input);
}
public void rollSet(String key){
int numD4 = Integer.parseInt(editNumD4.getText().toString());
int numD6 = Integer.parseInt(editNumD6.getText().toString());
int numD8 = Integer.parseInt(editNumD8.getText().toString());
int numD10 = Integer.parseInt(editNumD10.getText().toString());
int numD12 = Integer.parseInt(editNumD12.getText().toString());
int numD20 = Integer.parseInt(editNumD20.getText().toString());
for(int i = 0; i<numD4; i++){
Die d4 = new Die(4,key);
diceSetList.add(d4);
}
for(int i = 0; i<numD6; i++){
Die d6 = new Die(6,key);
diceSetList.add(d6);
}
for(int i = 0; i<numD8; i++){
Die d8 = new Die(8,key);
diceSetList.add(d8);
}
for(int i = 0; i<numD10; i++){
Die d10 = new Die(10,key);
diceSetList.add(d10);
}
for(int i = 0; i<numD12; i++){
Die d12 = new Die(12,key);
diceSetList.add(d12);
}
for(int i = 0; i<numD20; i++){
Die d20 = new Die(20,key);
diceSetList.add(d20);
}
DieSet dieSet = new DieSet(diceSetList,key);
int result = dieSet.rollTotal();
listener.setLogsUpdate(dieSet.getLOG());
listener.setResultsUpdate("Set Roll = " + result);
showAlert(result);
diceSetList.clear();
}
public void showAlert(int result){
new AlertDialog.Builder(Objects.requireNonNull(getContext()))
.setTitle("You rolled a: ")
.setMessage(Integer.toString(result))
.show();
}
public void onAttach(@NonNull Context context) {
super.onAttach(context);
if(context instanceof SetFragmentListener){
listener = (SetFragmentListener) getContext();
} else throw new RuntimeException(context.toString() + "must implement SetFragmentListener");
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
}
【问题讨论】:
标签: java android android-fragments android-viewpager