I'm trying to manage a RyclerView into my fragment. When I open the app, the fragment gets loaded and a list of element is generated too (this by the execution of the loadMovie() method). Now, I added a search button and I'd like to reload the loadMovie() method to refresh the list of elements. My problem is that even if the list changes, when I click on an element it opens me two new activities: the one of the object on which I clicked on and the one of the element that was in the same position of the current one before calling the method. How can I delete all the old elements of the RecyclerView without modify the Adapter? This is the code:
public class PopularFragment extends Fragment {
private EditText mSearchField;
private ImageButton mSearchBtn;
#BindView(R.id.rc_view)
RecyclerView recyclerView;
public PopularFragment() {
}
public static PopularFragment newInstance(String param1, String param2) {
PopularFragment fragment = new PopularFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onPause();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.popular_fragment, container, false);
recyclerView = view.findViewById(R.id.popular_rc_view);
mSearchField = (EditText) view.findViewById(R.id.search_field);
mSearchBtn = (ImageButton) view.findViewById(R.id.search_btn);
mSearchBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
loadMovie();
}
});
loadMovie();
return view;
}
#Override
public void onPause() {
super.onPause();
}
private void loadMovie() {
ApiService apiService = ApiBuilder.getClient(getContext()).create(ApiService.class);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext(),LinearLayoutManager.VERTICAL, false));
Call<MovieResponse> call = apiService.getPopular(Values.CATEGORY[1], BuildConfig.API_KEY,Values.LANGUAGE,Values.PAGE[0]);
call.enqueue(new Callback<MovieResponse>() {
#Override
public void onResponse(Call<MovieResponse>call, Response<MovieResponse> response) {
final List<MovieModel> movies = response.body().getResults();
recyclerView.setAdapter(new PopularAdapter(movies, R.layout.content_main, getContext()));
recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
GestureDetector gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
public boolean onSingleTapUp(MotionEvent e){
return true;
}
});
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && gestureDetector.onTouchEvent(e)){
int position = rv.getChildAdapterPosition(child);
//loadActivity
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
}
#Override
public void onFailure(Call<MovieResponse>call, Throwable t) {
}
});
}
}
Have you tried to define the Adapter class globally?
Try doing the following steps:-
Define the Adapter class globally and pass an empty list of movies.
Add a function in adapter that accepts the list of movies that you can call in place of defining your adapter over an over again.
Call (Adapter class variable).notifyDataSetChanged(); every time after you call the new function that populates your data, that'll refresh your list of data.
Related
I want to make my fragment wont re-load the data when configuration change with view model.
So, i try to make an App about gitHub User.
My Main Activity contain Search view to search user and show the result with recyclerview.
My Detail Activity is showing the detail of user when one of user in the list clicked, and in my detail activity i use Tab Layout and view pager to show user's followers and following.
My ViewModel for activity works well and can keep my data when orientation change.
But when i do the same to my fragment, my fragment keep re-loading new data when orientation change.
Here my fragment
i use View Model to request data
public class FollowingFragment extends Fragment {
public static final String KEY_FOLLOWING = "key_following";
private RecyclerView recyclerView;
private FollowingViewModel followingViewModel;
private FollowingAdapter followingAdapter;
ShimmerFrameLayout shimmerFrameLayout;
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
ArrayList<FollowingResponse> followingResponse = new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_following, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.rv_following);
shimmerFrameLayout = view.findViewById(R.id.shimmer_frame_layout2);
followingViewModel = ViewModelProviders.of(this).get(FollowingViewModel.class);
followingAdapter = new FollowingAdapter();
followingAdapter.setOnItemClickCallback(new FollowingAdapter.OnItemClickCallback() {
#Override
public void onItemClicked(FollowingResponse followingResponse) {
showSelectedItem(followingResponse);
}
});
//this is what i've tried and worked, but my fragment result with double or triple the data.
if (savedInstanceState == null){
}
else {
followingResponse = savedInstanceState.getParcelableArrayList(KEY_FOLLOWING);
}
showRecyclerView();
getData();
}
private void getData() {
followingViewModel.setDataFollowing(DetailUserActivity.clickedUser);
followingViewModel.getDataFollowing().observe(getViewLifecycleOwner(), new Observer<ArrayList<FollowingResponse>>() {
#Override
public void onChanged(ArrayList<FollowingResponse> followingResponses) {
shimmerFrameLayout.setVisibility(View.GONE);
shimmerFrameLayout.stopShimmer();
followingAdapter.setData(followingResponse);
followingResponse.addAll(followingResponses);
recyclerView.setAdapter(followingAdapter);
followingAdapter.notifyDataSetChanged();
}
});
}
private void showRecyclerView() {
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
}
#Override
public void onResume() {
super.onResume();
followingViewModel.setDataFollowing(DetailUserActivity.clickedUser);
}
private void showSelectedItem(FollowingResponse item) {
Intent intent = new Intent(getContext(), DetailUserActivity.class);
intent.putExtra("EXTRA_DATA", item.getLogin());
startActivity(intent);
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
outState.putParcelableArrayList(KEY_FOLLOWING, followingResponse);
super.onSaveInstanceState(outState);
}
}
Detail Activity
public class DetailUserActivity extends AppCompatActivity {
private TextView tvName, tvNickname, tvLocation, tvCompany, tvEmail, tvWebsite;
private TextView tvCountFollowers, tvCountRepository, tvCountFollowing;
private ImageView imgProfile;
ProgressBar progressBar;
public static String clickedUser;
UserViewModel userViewModel;
private ViewPager viewPager;
TabLayout tabLayout;
private final String EXTRA_DATA = "EXTRA_DATA";
private static final String EXTRA_FOLLOW = "extra_follow";
// Fragment followingFragment;
// FragmentTransaction transaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detail_user_activity);
// i've tried this, but when the orientation change, my detail activity force close and throw me to my main activity.
// if (savedInstanceState != null){
// followingFragment = getSupportFragmentManager().getFragment(savedInstanceState, KEY_FOLLOWING);
// } else {
// followingFragment = new FollowingFragment();
//
// getSupportFragmentManager().beginTransaction().replace(R.id.tv_view_pager, followingFragment).commit();
// }
tvName = findViewById(R.id.tv_item_name);
tvNickname = findViewById(R.id.tv_item_nickname);
tvLocation = findViewById(R.id.tv_item_location);
tvCompany = findViewById(R.id.tv_item_company);
tvEmail = findViewById(R.id.tv_item_email);
tvWebsite = findViewById(R.id.tv_item_website);
imgProfile = findViewById(R.id.img_item_photo);
tvCountFollowers = findViewById(R.id.tv_count_follower);
tvCountRepository = findViewById(R.id.tv_count_repo);
tvCountFollowing = findViewById(R.id.tv_count_following);
progressBar = findViewById(R.id.progressbar2);
setForUserData();
setForTabLayout();
}
private void setForUserData(){
Intent detailIntent = getIntent();
clickedUser = detailIntent.getStringExtra("EXTRA_DATA");
userViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(UserViewModel.class);
userViewModel.setUserUVM(clickedUser);
userViewModel.getUserUVM().observe(this, new Observer<UserResponse>() {
#Override
public void onChanged(UserResponse userResponse) {
progressBar.setVisibility(View.GONE);
Glide.with(getApplicationContext())
.load(userResponse.getAvatarUrl())
.into(imgProfile);
tvName.setText(userResponse.getLogin());
tvLocation.setText(userResponse.getLocation());
tvNickname.setText(userResponse.getName());
tvCompany.setText(userResponse.getCompany());
tvEmail.setText(userResponse.getEmail());
tvWebsite.setText(userResponse.getBlog());
tvCountRepository.setText(String.valueOf(userResponse.getPublicRepos()));
tvCountFollowers.setText(String.valueOf(userResponse.getFollowers()));
tvCountFollowing.setText(String.valueOf(userResponse.getFollowing()));
}
});
}
private void setForTabLayout(){
tabLayout = findViewById(R.id.tv_tab_layout);
viewPager = findViewById(R.id.tv_view_pager);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount()));
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setTabMode(TabLayout.MODE_FIXED);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
int totalTab;
#SuppressWarnings("deprecation")
ViewPagerAdapter(FragmentManager fragmentManager, int totalTabs) {
super(fragmentManager);
this.totalTab = totalTabs;
}
#SuppressWarnings("ConstantConditions")
#NonNull
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return new FollowersFragment();
case 1:
return new FollowingFragment();
default:
return null;
}
}
#Override
public int getCount() {
return totalTab;
}
}
// #Override
// protected void onSaveInstanceState(#NonNull Bundle outState) {
// getSupportFragmentManager().putFragment(outState, KEY_FOLLOWING, followingFragment );
// super.onSaveInstanceState(outState);
// }
}
im trying to solve my FollowingFragment first, then ill do the same on my FollowerFragment.
im really new in programming, and have no one to ask.. can someone help me to solve my problem with keep data in fragment when orientation change?
followingViewModel = ViewModelProviders.of(this).get(FollowingViewModel.class);
In Fragment insted of writing this code in onViewCreated() write it inside OnCreate()
onViewCreated() will get called everytime the orientation changes so it will create new instance of view model everytime the orientation changes making viewmodel to reload the data
If you need to load data only once for the FollowingViewModel a good place to do it should be inside the constructor of the view model in this way you won't need to worry about the orientation change of the fragment.
I have a List of Users with 2 TabItem. The first TabItem is MyUsers and the second one is Favorites. I use a foreach loop to sort the Users. Now, that I want, is to display the Users List into MyUsers and after my loop display the sorted Users into Favorites.
UserFragment.java
public class UserFragment extends Fragment implements MyUserRecyclerViewAdapter.OnItemListener {
#BindView(R.id.tabs)
TabLayout mTabLayout;
#BindView(R.id.tabItem)
TabItem mTabItemMyUsers;
#BindView(R.id.tabItem2)
TabItem mTabItemFavorites;
private UserApiService mApiService;
private List<User> mUsers;
private List<User> mFavorites;
private RecyclerView mRecyclerView;
private int mPosition;
public static UserFragment newInstance(int position) {
UserFragment userFragment = new UserFragment();
Bundle args = new Bundle();
args.putInt("position", position);
userFragment.setArguments(args);
return userFragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mApiService = DI.getUserApiService();
mPosition = getArguments().getInt("position", 0);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_user_list, container, false);
Context context = view.getContext();
mRecyclerView = (RecyclerView) view;
mRecyclerView.setLayoutManager(new LinearLayoutManager(context));
mRecyclerView.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));
initList();
isUserFavorite();
return view;
}
public void isUserFavorite() {
mFavorites = new ArrayList<>();
for (User user : mUsers) {
if (user.isFavorite()) {
mFavorites.add(user);
}
}
mRecyclerView.setAdapter(new MyUserRecyclerViewAdapter(mFavorites, this));
}
private void initList() {
mUser = mApiService.getUsers();
mRecyclerView.setAdapter(new MyUserRecyclerViewAdapter(mUsers, this));
}
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
If I understood your question right. You will be creating two lists, one unordered list of users as received and second with list of users marked as favorites. And then you want to switch which list to show in the single RecyclerView in your fragment's layout by clicking on one of the two tabs in your TabLayout in the same layout.
You should simply populate the lists first instead of setting them both into RecyclerView at once, then manage tab selections on your mTabLayout using an addOnTabSelectedListener inside which you can choose the list to set into your recyclerview, since you have already defined a LayoutManager for your list, next finally use notifyDataSetChanged() on your adapter to to update the views.
So keeping most of your logic the same your code would need to be refactored to something like this:
...
#Override
public View onCreateView(La...) {
...
mRecyclerView.setLayoutManager(new LinearLayoutManager(context));
...
initList();
isUserFavorite();
initSelection();
return view;
}
public void isUserFavorite() {
mFavorites = new ArrayList<>();
for (User user : mUsers) {
if (user.isFavorite()) {
mFavorites.add(user);
}
}
}
private void initList() {
mUser = mApiService.getUsers();
}
public void initSelection() {
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
// assuming users is at tab index 0 and favorites is at tab Index 1
if(tab.getPosition() == 1) {
selectFavorites();
} else {
selectUsers();
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
// if you wish to select the users tab at 0 by default
Objects.requireNonNull(mTabLayout.getTabAt(0)).select();
}
private void selectFavorites() {
// whichever adapter you were using to show favorites
MyUserRecyclerViewAdapter mFavAdapter = new MyUserRecyclerViewAdapter(mFavorites, context);
mRecyclerView.setAdapter(mFavAdapter);
mFavAdapter.notifyDataSetChanged();
}
private void selectUsers() {
// whichever adapter you were using to show all users
MyNeighbourRecyclerViewAdapter mUsersAdapter = new MyNeighbourRecyclerViewAdapter(mUsers, context);
mRecyclerView.setAdapter(mUsersAdapter);
mFavAdapter.notifyDataSetChanged();
}
Hope this was what you were looking for.
I'm having a problem with making a RecycleView in a fragment with data from Firebase. I expect the app to show the RecycleView after I clicked on a button to change from one fragment to the RecycleView fragment, but it does change the showed fragment but it does not show anything.
I know there are plenty of questions like this but I don't seem to find the correct solution to this problem.
I've made everything needed for a Firebase RecyclerView, and also tried to build it inside an activity instead fragment and it did work, but not with the fragment.
I've tried to initialize the adapter and recyclerview inside the onCreateView method, onActivityCreated, and onViewCreated method and none of them seem to be working.
Here's my fragment code:
private KidAdapter adapter;
private RecyclerView recyclerView;
Button button;
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.uangsaku_menu_fragment, container, false);
button = view.findViewById(R.id.btn_add);
button.setOnClickListener(this);
recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
setUpRecyclerView();
return view;
}
#Override
public void onClick(View v) {
if(v.getId() == R.id.btn_add){
Intent intent = new Intent(getActivity(), Register.class);
startActivity(intent);
}
}
public void setUpRecyclerView(){
Query query = FirebaseDatabase.getInstance().getReference("kids");
FirebaseRecyclerOptions<kidData> options = new FirebaseRecyclerOptions.Builder<kidData>()
.setQuery(query, kidData.class)
.build();
adapter = new KidAdapter(options);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(adapter);
}
#Override
public void onStart() {
super.onStart();
if (adapter != null) {
adapter.startListening();
}
}
#Override
public void onStop() {
super.onStop();
if (adapter != null) {
adapter.stopListening();
}
}
}
The adapter class
public class KidAdapter extends FirebaseRecyclerAdapter<kidData, KidAdapter.KidViewHolder> {
public KidAdapter(#NonNull FirebaseRecyclerOptions<kidData> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull KidViewHolder holder, int position, #NonNull kidData model) {
holder.nama.setText(model.getKidName());
holder.balance.setText(model.getKidBalance());
holder.limit.setText("Limit: "+model.getKidLimit());
holder.spending.setText("Spending xxx.xxx");
}
#NonNull
#Override
public KidViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.kids_card,
viewGroup, false);
return new KidViewHolder(v);
}
public class KidViewHolder extends RecyclerView.ViewHolder {
TextView nama, balance, limit, spending;
public KidViewHolder(#NonNull View itemView) {
super(itemView);
nama = itemView.findViewById(R.id.tv_nama);
balance = itemView.findViewById(R.id.tv_balance);
limit = itemView.findViewById(R.id.tv_dailylimit);
spending = itemView.findViewById(R.id.tv_dailyspending);
}
}
}
The kidData model class
public class kidData {
String kidName, kidEmail, kidDoB, kidLimit, kidBalance;
public kidData(){
}
public kidData(String kidName, String kidEmail, String kidDoB, String kidLimit, String kidBalance) {
this.kidName = kidName;
this.kidEmail = kidEmail;
this.kidDoB = kidDoB;
this.kidLimit = kidLimit;
this.kidBalance = kidBalance;
}
public String getKidName() {
return kidName;
}
public String getKidEmail() {
return kidEmail;
}
public String getKidDoB() {
return kidDoB;
}
public String getKidLimit() {
return kidLimit;
}
public String getKidBalance() {
return kidBalance;
}
}
The problem in your code is the use of the following line of code:
recyclerView.setHasFixedSize(true);
And this is because when using the latest version of Firebase-UI library, there is no need to set the size of the RecyclerView as fixed. The solution for solving this problem is to simply remove/comment the above line of code. That's it!
I'm trying to implement text counter where an integer will be incremented and decremented inside each firestore RecyclerView item for example 0 to 100. I've tried taking an int[] and Button onClick. I did holder.tvqty.setText(String.valueOf(a[position]++));. Here on Button click, all TextViews are successfully incremented with individual items. But the main problem is that when I click on first item button if the first position is the same, it's actually also incrementing last position i.e, in short, the first and last RecyclerView items are getting incremented together however rest of the items are working without any problem.
Please help me debug this any help will be appreciated.
This is my java class:
public class OrderItemFragment extends Fragment{
Context context;
int i=0;
// private List<Ex> exlist;
RecyclerView recyclerView;
FirebaseFirestore db;
FirestoreRecyclerAdapter adapter;
ArrayList<String> list = new ArrayList<String>();
int [] a;
public static OrderItemFragment newInstance() {
OrderItemFragment fragment = new OrderItemFragment();
return fragment;
}
public OrderItemFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_orderitem, container, false);
LinearLayoutManager layoutManager
= new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
recyclerView = (RecyclerView) view.findViewById(R.id.recorder);
recyclerView.setLayoutManager(layoutManager);
initializeData();
//initializeAdapter();
db=FirebaseFirestore.getInstance();
return view;
}
private void initializeData()
{
db=FirebaseFirestore.getInstance();
Query query = db.collection("Items");
FirestoreRecyclerOptions<FriendsResponse> response = new FirestoreRecyclerOptions.Builder<FriendsResponse>()
.setQuery(query, FriendsResponse.class)
.build();
adapter = new FirestoreRecyclerAdapter<FriendsResponse, FriendsHolder>(response) {
#Override
public void onBindViewHolder(FriendsHolder holder, int position, FriendsResponse model) {
/* for (int i=0;i < ids.size();i++)
{
holder.exname.setText(ids.get(i));
}*/
//Toast.makeText(getContext(),String.valueOf(getItemCount()),Toast.LENGTH_LONG).show();
// String id = getSnapshots().getSnapshot(position).getId();
String id = getSnapshots().getSnapshot(position).getId();
for (i=0;i<getSnapshots().size();i++) {
list.add(getSnapshots().getSnapshot(position).getId());
}
a= new int [list.size()];
holder.exname.setText(id);
holder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.tvqty.setText(String.valueOf(a[position]++));
}
});
holder.remove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
#Override
public FriendsHolder onCreateViewHolder(ViewGroup group, int i) {
View view = LayoutInflater.from(group.getContext())
.inflate(R.layout.menu_item, group, false);
return new FriendsHolder(view);
}
#Override
public void onError(FirebaseFirestoreException e) {
Log.e("error", e.getMessage());
}
};
adapter.notifyDataSetChanged();
recyclerView.setAdapter(adapter);
}
public class FriendsHolder extends RecyclerView.ViewHolder {
TextView exname,tvqty;
ImageView add,remove;
public FriendsHolder(View itemView) {
super(itemView);
exname= itemView.findViewById(R.id.menuname);
add=itemView.findViewById(R.id.additem);
remove=itemView.findViewById(R.id.removeitem);
tvqty=itemView.findViewById(R.id.tvqty);
}
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
/*
public class Ex {
String name;
int logoId;
int count=0;
Ex(String name, int logoId) {
this.name = name;
this.logoId = logoId;
}
}
*/
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
}
In this line of code holder.tvqty.setText(String.valueOf(a[position]++)), does a[position]++ the job ? Try to store the value of a[position] in a integer,and after that set it to tvqty.
int current_value = a[position];
and then
holder.tvqty.setText(String.valueOf((current_value++)));
I am new to android studio. Please help. I have an app with 3 fragments, one have list of video view using recycler adapter, one have list of image view, other have same list of video view as no 1 fragment. First and last fragment are using same adapter. The problem is that while switching fragmment from first one to second video keeps playing.
//fragment code
public class funny_moments extends Fragment {
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("funnymomments");
ArrayList<funny_momments_row> data;
funny_momments_adapter adapter;
VideoView mVideoView;
View pos;
private RecyclerView mRecyclerView;
public funny_moments() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_funny_moments, container, false);
mRecyclerView =(RecyclerView) view.findViewById(R.id.recylerview);
mVideoView = (VideoView)view.findViewById(R.id.videoView);
data = new ArrayList<>();
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot videoSnapshot : dataSnapshot.getChildren()){
funny_momments_row video = new funny_momments_row(videoSnapshot.child("like").getValue().toString(),videoSnapshot.child("url").getValue().toString());
data.add(video);
}
adapter = new funny_momments_adapter(getActivity(),data,mCommunication);
mRecyclerView.setAdapter(adapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
// Inflate the layout for this fragment
return view;
}
#Override
public void onPause() {
adapter.mMediaPlayer.pause();
super.onPause();
}
//adapter code
public class funny_momments_adapter extends RecyclerView.Adapter<funny_momments_adapter.funnyVideoHolder> {
private final LayoutInflater inflator;
List<funny_momments_row> data = Collections.emptyList();
communication mCommunicator;
Context mContext;
public funny_momments_adapter(Context context, List<funny_momments_row> data, communication communicator){
inflator = LayoutInflater.from(context);
this.data = data;
this.mContext = context;
mCommunicator = communicator;
}
#NonNull
#Override
public funnyVideoHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = inflator.inflate(R.layout.funny_momments_row,viewGroup,false);
funnyVideoHolder funnyHolder = new funnyVideoHolder(view,mCommunicator);
return funnyHolder;
}
#Override
public void onBindViewHolder(#NonNull final funnyVideoHolder viewHolder, int i) {
funny_momments_row current = data.get(i);
VideoView f1 = viewHolder.mVideoView;
viewHolder.mVideoView.setVideoURI(Uri.parse(current.getUrl()));
viewHolder.likecount.setText(current.getLike());
viewHolder.mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(final MediaPlayer mp) {
FragmentManager manager = ((AppCompatActivity)mContext).getSupportFragmentManager();
Fragment f = manager.findFragmentByTag("android:switcher:" + R.id.viewPager + ":" + 2);
mMediaPlayer = mp;
viewHolder.playpause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mp.isPlaying()) {
mp.pause();
}
else {
mp.start();
}
}
});
}
});
viewHolder.playpause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (viewHolder.mVideoView.isPlaying()) {
viewHolder.mVideoView.requestFocus();
viewHolder.mVideoView.pause();
}
else {
viewHolder.mVideoView.requestFocus();
viewHolder.mVideoView.start();
}
}
});
}
#Override
public int getItemCount() {
return data.size();
}
public class funnyVideoHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
VideoView mVideoView;
ImageView likeicon;
TextView likecount;
ImageView playpause;
communication mCommunication;
public funnyVideoHolder(#NonNull View itemView,communication communication) {
super(itemView);
mVideoView = (VideoView)itemView.findViewById(R.id.videoView);
likeicon = (ImageView)itemView.findViewById(R.id.likeicon);
likecount = (TextView)itemView.findViewById(R.id.likecount);
playpause = (ImageView)itemView.findViewById(R.id.playpause);
mCommunication = communication;
}
#Override
public void onClick(View v) {
mCommunication.respond(v);
}
}
}
I want to stop playback while switching fragment.
When you fragment from one fragment to another, previous fragment's onPause() is called (giving you the opportunity to pause the video) and new fragment's onResume() function is called. If new fragment was not already created, onStart,onCreate() etc method are called before onResume() is called.
What you can do, when a fragment gets out of focus, thus called onPause(), pause your video, and when a fragment get in focus, you can resume it if it was already create.
Fragment Lifecycle (source)