从另一个片段中的目录更新片段中的列表视图元素
Posted
技术标签:
【中文标题】从另一个片段中的目录更新片段中的列表视图元素【英文标题】:Updating Elements of Listview in a Fragment from a Catalog within another Fragment 【发布时间】:2020-05-15 07:10:01 【问题描述】:标题可能有点混乱,所以我希望我能正确表达我的问题。所以我正在开发一个简单的锻炼日志应用程序。我有如图 1 所示的片段 ActiveWorkout。当我按下粉红色的添加按钮时,我被定向到另一个片段,其中包含不同的练习作为列表,如图 2 所示。然后我要选择一个练习(使用 onItemClickListener)并且该练习的标题应该被发送回 ActiveWorkoutFragment 并添加到 Active Workout,所以它应该像图 3。所以这里的问题是,我不完全知道如何让我的 Active Workout 保持“活力”,如果我想添加另一个练习并且当我再次按下粉红色的添加按钮时它不是空白的,它应该被更新,所以最后它应该像图 4 中的那样。我正在考虑使用 Bundle 发送数据,我也在代码中进行了尝试,但更困难的部分是在不删除之前添加的练习的情况下更新锻炼列表。顺便说一句,我尝试这样做的原因是因为数据实际上在 Firebase 数据库中,所以从某种意义上说,我正在尝试从 Workout 数据库中检索数据。
图片:
Image 1Image 2Image 3Image 4
这是练习列表或目录:
public class ExercisesFragment extends Fragment
private ListView lv;
private FirebaseListAdapter adapter;
private ArrayList<Exercise> exerciseList;
private ArrayList<String> nameList;
//private Adapter adapter;
public ExercisesFragment()
// Required empty public constructor
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
View v = inflater.inflate(R.layout.fragment_exercises, container, false);
lv = v.findViewById(R.id.lv);
Query query = FirebaseDatabase.getInstance().getReference().child("exerciseList");
FirebaseListOptions<ExerciseElement> options = new FirebaseListOptions.Builder<ExerciseElement>()
.setLayout(R.layout.exercise)
.setQuery(query, ExerciseElement.class)
.build();
adapter = new FirebaseListAdapter(options)
@Override
protected void populateView(@NonNull View v, @NonNull Object model, int position)
TextView bodypart = v.findViewById(R.id.bodypart);
TextView title = v.findViewById(R.id.title);
ExerciseElement el = (ExerciseElement) model;
bodypart.setText(el.getBodypart().toString());
title.setText(el.getTitle().toString());
;
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
ExerciseElement el = (ExerciseElement) lv.getItemAtPosition(position);
String item = el.getTitle();
ActiveWorkoutFragment awf = new ActiveWorkoutFragment();
Bundle args = new Bundle();
args.putString("ExerciseTitle", item);
awf.setArguments(args);
getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, awf).commit();
//Navigation.findNavController(v).navigate(R.id.activeWorkoutFragment);
);
return v;
@Override
public void onStart()
super.onStart();
adapter.startListening();
@Override
public void onStop()
super.onStop();
adapter.stopListening();
然后是ActiveWorkoutFragment,它有点长,但上部不是问题。当我点击粉红色的添加按钮时,会调用 addNewExercise() 方法,所以我试图在那里以某种方式检索数据。
public class ActiveWorkoutFragment extends Fragment
private Workout workout;
private TextView emptyRecyclerView;
private RecyclerView exerciseRecyclerView;
private ExerciseRecyclerViewAdapter adapter;
private WorkoutHistory workoutHistory;
private FloatingActionButton fab;
private FirebaseAuth mAuth;
private DatabaseReference databaseWorkouts;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
View v = inflater.inflate(R.layout.fragment_active_workout, container, false);
fab = v.findViewById(R.id.fab);
fab.setOnClickListener(this::addNewExercise);
setHasOptionsMenu(true);
workout = new Workout("WORKOUT");
if(savedInstanceState != null)
workout = savedInstanceState.getParcelable("key");
emptyRecyclerView = v.findViewById(R.id.empty_recycler_view);
//buildRecyclerView(workout);
exerciseRecyclerView = v.findViewById(R.id.recycler_view_exercise);
// improves performance if size of RecyclerView content is fixed
// taken from developer.android.com
exerciseRecyclerView.setHasFixedSize(true);
// use a linear layout manager for RecyclerView
LinearLayoutManager layoutManager = new LinearLayoutManager(this.getContext());
exerciseRecyclerView.setLayoutManager(layoutManager);
// add divider
RecyclerView.ItemDecoration itemDecoration = new
DividerItemDecoration(this.getContext(), DividerItemDecoration.VERTICAL);
exerciseRecyclerView.addItemDecoration(itemDecoration);
// Create adapter and set its data set to workout
adapter = new ExerciseRecyclerViewAdapter(workout, this);
// Set up swipe to dismiss and ability to move RecyclerView items around
// Create callback object for ItemTouchHelper
ItemTouchHelper.Callback callback = new CustomItemTouchHelperCallback(adapter);
// Implement object created above
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
touchHelper.attachToRecyclerView(exerciseRecyclerView);
if (adapter.getItemCount() == 0)
showEmptyRecyclerViewText();
else
exerciseRecyclerView.setAdapter(adapter);
return v;
// Adds save button (check mark) to action bar
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
inflater.inflate(R.menu.active_workout_action_bar, menu);
super.onCreateOptionsMenu(menu, inflater);
@Override
public boolean onOptionsItemSelected(MenuItem item)
switch (item.getItemId())
case R.id.action_save:
List<Exercise> exercises = workout.getExercises();
mAuth = FirebaseAuth.getInstance();
String user_id = mAuth.getCurrentUser().getUid();
databaseWorkouts = FirebaseDatabase.getInstance().getReference("Workouts").child(user_id);
String id = databaseWorkouts.push().getKey();
workout = new Workout("abc", user_id, exercises);
databaseWorkouts.child(id).setValue(workout);
Toast.makeText(getContext(), "Workout saved", Toast.LENGTH_SHORT).show();
return true;
case R.id.action_delete:
exerciseRecyclerView.requestFocus();
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("Confirm deletion").setMessage("Are you sure you want to delete" +
" this workout?");
builder.setPositiveButton(android.R.string.yes, (dialog, which) ->
try
workoutHistory.removeWorkout(workout);
catch (IOException e)
e.printStackTrace();
Toast.makeText(getContext(), "Workout deleted", Toast.LENGTH_SHORT).show();
);
builder.setNegativeButton(android.R.string.no, (dialog, which) ->
dialog.dismiss();
);
builder.show();
return true;
default:
// unrecognized button pressed
return super.onOptionsItemSelected(item);
public void showEmptyRecyclerViewText()
emptyRecyclerView.setVisibility(View.VISIBLE);
public void addNewExercise(View view)
Bundle bundle = getArguments();
String value = "";
if(bundle != null)
value = bundle.getString("ExerciseTitle");
System.out.println("lala");
System.out.println(value);
Exercise newExercise = new Exercise(value, -1, -1);
if (exerciseRecyclerView.getAdapter() == null)
exerciseRecyclerView.setAdapter(adapter);
emptyRecyclerView.setVisibility(View.INVISIBLE);
workout.addExercise(newExercise);
adapter.notifyItemInserted(workout.getExercises().size() - 1);
private void hideKeyboard(Context context, View view)
InputMethodManager imm = (InputMethodManager) context.getSystemService
(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
@Override
public void onSaveInstanceState(@NonNull Bundle outState)
super.onSaveInstanceState(outState);
outState.putParcelable("key", workout);
【问题讨论】:
所以主要问题是当您从 image2 选择到 image1 时 .. image1 没有更新,换句话说,它重新创建了? 请避免使用 ListView 而使用 RecyclerView 是的,实际上就是这样。我的意思是片段之间的数据传输是这里的一件事,但就像你说的主要问题是当我点击粉红色的添加按钮时,必须更新 image1 而不能一次又一次地重新创建。我也应该在这里使用 Bundle 来传输数据吗?我其实只转Strings,也就是题名。 ListView的缺点是什么,我对这个概念很陌生。 Recyclerview 使用 ViewHolder 模式强制回收视图。所以它增加了性能并被社区推荐,而不是过时的 oof ListView 【参考方案1】:尝试将此作为您项目的基础。向它添加视图和其他必要的方法,但是它将为您提供模块的流程
//contract to update Framgents
public interface FragUpdater
public void updateExerciseFrag(Exercise exercise);
public class ExerciseActiity extends AppCompatActivity implements FragUpdater
FragmentManager fm;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exercise_actiity);
fab.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
gotoActiveWorkoutFragment();
);
fm = getSupportFragmentManager();
gotoExercisesFragment();
private void gotoActiveWorkoutFragment()
ActiveWorkoutFragment activeWorkoutFragment = new ActiveWorkoutFragment();
Bundle bundle = new Bundle();
activeWorkoutFragment.setArguments(bundle);
fm.beginTransaction().add(R.id.content_frame, activeWorkoutFragment, "ExerciseSelectionFrag").addToBackStack(null).commit();
private void gotoExercisesFragment()
ExercisesFragment exercisesFragment = new ExercisesFragment();
Bundle bundle = new Bundle();
exercisesFragment.setArguments(bundle);
fm.beginTransaction().replace(R.id.content_frame, exercisesFragment, "ExerciseDisplayFrag").commit();
@Override
public void updateExerciseFrag(Exercise exercise)
// Get Fragment ExercisesFragment
ExercisesFragment frag = (ExercisesFragment)
fm.findFragmentByTag("ExerciseDisplayFrag");
if (frag == null)
return;
frag.updateList(exercise);
public class ExercisesFragment extends Fragment
//here update your list in ExerciseFragment
public void updateList(Exercise exercise)
public class ActiveWorkoutFragment extends Fragment
FragUpdater fragUpdater;
@Override
public void onCreate(@Nullable Bundle savedInstanceState)
super.onCreate(savedInstanceState);
fragUpdater = (ExerciseActiity) getActivity();
private void selectListItem(Exercise exercise)
fragUpdater.updateExerciseFrag(exercise);
getActivity().getSupportFragmentManager().popBackStack();
【讨论】:
以上是关于从另一个片段中的目录更新片段中的列表视图元素的主要内容,如果未能解决你的问题,请参考以下文章
无法从 ViewPager 中的另一个片段刷新/更新片段中的列表视图