Unable to send fragments back in Java - java

I am currently developing an Android mobile application and I encountered a problem. Although I tried and searched many sites and resources in stackoverflow, I could not find the solution. I am sharing my codes below.
What I want to do i want the fragments to go back when the back button is pressed, but it goes back to the activity part. As a result of how many Fragments are clicked, it returns to the activity part. What can I do. Sorry for my missing English.
InternalFilesActivity
public class InternalFilesActivity extends AppCompatActivity {
private FragmentManager manager;
private FragmentTransaction transaction;
private File[] files;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_internal_files);
String path = Environment.getExternalStorageDirectory().toString();
File directory = new File(path);
files = directory.listFiles();
manager = getSupportFragmentManager();
Fragment fr = FilesFragment.newInstance(files);
transaction = manager.beginTransaction();
transaction.add(R.id.fragment_container, fr);
transaction.commit();
}
#Override
public void onBackPressed() {
if (manager.getBackStackEntryCount() > 1) {
manager.popBackStackImmediate();
} else {
super.onBackPressed();
}
}
}
FilesFragment
public class FilesFragment extends Fragment {
private static File[] frFiles;
public FilesFragment() {
}
public static FilesFragment newInstance(File[] files) {
FilesFragment fragment = new FilesFragment();
frFiles = files;
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_files, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ListView internalList = view.findViewById(R.id.lv_internal);
InternalListAdapter adapter = new InternalListAdapter(frFiles, getContext(), getActivity());
internalList.setAdapter(adapter);
}
}
InternalListAdapter
public class InternalListAdapter extends BaseAdapter {
public File[] dataList;
public Context context;
public FragmentActivity activity;
public InternalListAdapter(File[] dataList, Context context, FragmentActivity activity) {
this.dataList = dataList;
this.context = context;
this.activity = activity;
}
#Override
public int getCount() {
return dataList.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = LayoutInflater.from(context).inflate(R.layout.internal_list_item, parent, false);
TextView fileName = convertView.findViewById(R.id.tv_file_name);
fileName.setText(dataList[position].getName());
ImageView listImage = convertView.findViewById(R.id.iv_list_image);
if (dataList[position].isDirectory()) {
listImage.setImageResource(R.drawable.ic_directory);
} else {
listImage.setImageResource(R.drawable.ic_file);
}
LinearLayout listItemLayout = convertView.findViewById(R.id.ll_list_item);
listItemLayout.setOnClickListener(v -> {
if (dataList[position].isDirectory()) {
createFragment(position);
}
});
return convertView;
}
private void createFragment(int position) {
FragmentManager manager = activity.getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Fragment fr = FilesFragment.newInstance(dataList[position].listFiles());
transaction.replace(R.id.fragment_container, fr);
transaction.commit();
}
}

in back press you have implemented Fragment popping up from back stack, but you are not adding your fragments to back stack in fact
use addToBackStack(someName) method for putting your fragments in there and then your back press should start working (more info in this SO topic)
manager = getSupportFragmentManager();
Fragment fr = FilesFragment.newInstance(files);
transaction = manager.beginTransaction();
transaction.addToBackStack("initialFragment"); // also may be null
transaction.add(R.id.fragment_container, fr);
transaction.commit();

check my answer.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
int count = getSupportFragmentManager().getBackStackEntryCount();
if(count==1){
finish();
}
}
return super.onKeyDown(keyCode,event);
}

SOLVED
The problem was that I used fragment as an instance. The problem was resolved when I created and used a new object.
private static File[] files;
public FilesFragment(File[] files) {
this.files = files;
}
I used the new FileManager() code instead of FileFragment.newInstance()

Related

Material Container Transform animation not working in Java

Im trying to use Material Container Transform in Recyclerview Adapter as described by this post MaterialContainerTransform transition is not Working on Return , but after implementing this in my project im getting null pointer exception error.
As everyone know Material Container Transform animation tutorials are in kotlin and im doing it in java.
So if anyone know how to properly use material container transform animation in recyclerview and point out my mistakes i will be very much thankful to him.
RecyclerView Adapter Class(source)
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements Filterable {
private Context context;
private List<Astadhyayi> wordList;
private List<Astadhyayi> filwordList;
private DictionaryDB dictionaryDB;
private OnclickListenerInterface listener;
public RecyclerViewAdapter(Context context, List<Astadhyayi> itemList, DictionaryDB dictionaryDB) {
this.context = context;
this.wordList = itemList;
this.dictionaryDB = dictionaryDB;
filwordList = new ArrayList<Astadhyayi>(itemList);
}
public void setClickListener(OnclickListenerInterface onclickListener) {
this.listener = onclickListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.wordslist_two_rv, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Astadhyayi word = wordList.get(position);
holder.rsutras.setText(word.mSutras);
// Animation******
holder.rsutras.setTransitionName(word.getMSutras());
if (word.mStatus != null && word.mStatus.equals(DictionaryDB.BOOKMARKED)) {
holder.bookmark.setImageResource(R.drawable.cards_heart);
} else {
holder.bookmark.setImageDrawable(null);
}
}
#Override
public Filter getFilter() {
return Searched_Filter;
}
private Filter Searched_Filter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<Astadhyayi> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(filwordList);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (Astadhyayi item : filwordList) {
if (item.getMSutras().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
wordList.clear();
wordList.addAll((ArrayList<Astadhyayi>)results.values);
notifyDataSetChanged();
}
};
#Override
public int getItemCount() {
return wordList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView rsutras;
private ImageView bookmark;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
rsutras = itemView.findViewById(R.id.tvSansTerm);
bookmark = itemView.findViewById(R.id.bookmarkBtn);
}
/*
#Override
public void onClick(View view) {
if(listener!=null) listener.onItemClicked(getAbsoluteAdapterPosition(), rsutras);
}
*/
#Override
public void onClick(View view) {
int position = this.getAbsoluteAdapterPosition();
Astadhyayi word = wordList.get(position);
//*************** Bundle **************\\
Bundle bundle = new Bundle();
bundle.putParcelable("allData", word);
bundle.putString("transition_name", word.getMSutras());
Fragment detailsFragment = new TermThreeDetailsFragment();
detailsFragment.setSharedElementEnterTransition(new MaterialContainerTransform());
detailsFragment.setArguments(bundle);
FragmentTransaction fT =((AppCompatActivity)context).getSupportFragmentManager().beginTransaction();
fT.setReorderingAllowed(true);
fT.addSharedElement(rsutras, rsutras.getTransitionName()); // Shared element!
fT.replace(R.id.fragment_container, detailsFragment);
fT.addToBackStack(null);
fT.commit();
}
}
}
RecyclerView Fragment Class(source)
public class ShowtermsTwoFragment extends Fragment {
private RecyclerView rv;
private EditText tV;
private Toolbar toolbar;
private LinearLayoutManager layoutManager;
private static DictionaryDB db;
private RecyclerViewAdapter rvAdapter;
private SearchView searchView = null;
private SearchView.OnQueryTextListener queryTextListener;
private List<Astadhyayi> wordsList = new ArrayList<>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setExitTransition(new MaterialElevationScale(false));
setReenterTransition(new MaterialElevationScale(true));
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_terms_recyclerview, container, false);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toolbar = ((Toolbar) view.findViewById(R.id.toolbar_rv));
rv = view.findViewById(R.id.rvTerms);
tV = view.findViewById(R.id.tVinput);
//*********** TOOLBAR
AppCompatActivity activity = (AppCompatActivity) getActivity();
activity.setSupportActionBar(toolbar);
setHasOptionsMenu(true);
// new Get_DbData().execute();
databaseCheck();
recyclerCheck1();
postponeEnterTransition();
((ViewGroup) view.getParent()).getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
startPostponedEnterTransition();
return true;
}
});
}
private void databaseCheck() {
String sanskritWord = getActivity().getIntent().getStringExtra("sanskritWord");
//*********** ### DATABASE OPENING ### ***********\\
db = DictionaryDB.getInstance(this.getActivity());
wordsList = db.getWords((sanskritWord));
}
private void recyclerCheck1() {
layoutManager = new LinearLayoutManager(getContext());
rv.setLayoutManager(layoutManager);
rv.setHasFixedSize(true);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(rv.getContext(), layoutManager.getOrientation());
rv.addItemDecoration(dividerItemDecoration);
rvAdapter = new RecyclerViewAdapter(getContext(), wordsList, db);
rv.setAdapter(rvAdapter);
/////********** rvAdapter.setClickListener(this);
rvAdapter.notifyDataSetChanged();
}
}
Details Fragment Class(destination)
public class TermThreeDetailsFragment extends Fragment {
private TextView sutraTV,vrittiTV,padaTv,adhyayTV,sutraIdTV ;
private CoordinatorLayout coordinatorLayout;
private FloatingActionButton fabBtn;
private static DictionaryDB db;
private Astadhyayi word;
private BottomAppBar bottomAppBar;
private TextToSpeech pronunciation;
private AudioManager audio;
private String ttsID , trans;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MaterialContainerTransform transform = new MaterialContainerTransform();
transform.setScrimColor(Color.TRANSPARENT);
setSharedElementEnterTransition(transform);
setSharedElementReturnTransition(transform);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.show_three_details, container, false);
view.findViewById(R.id.tvSutra).setTransitionName(word.getMSutras());
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
sutraTV = view.findViewById(R.id.tvSutra);
adhyayTV = view.findViewById(R.id.tVAdhyay);
padaTv = view.findViewById(R.id.tVPada);
sutraIdTV = view.findViewById(R.id.tVSutraId);
vrittiTV = view.findViewById(R.id.tvVritti);
fabBtn = view.findViewById(R.id.favFAB);
coordinatorLayout = view.findViewById(R.id.parentCordlayout);
bottomAppBar = view.findViewById(R.id.bottom_app_bar);
bundleCheckWithDb();
WordCheck();
}
private void bundleCheckWithDb() {
//*********** Geting Parcelable Data
word = new Astadhyayi(Parcel.obtain());
Bundle bundle = this.getArguments();
if (bundle != null) {
word = bundle.getParcelable("allData");
trans = bundle.getString("transition_name");
adhyayTV.setText(word.getMAdhyay());
padaTv.setText(word.getMPada());
sutraIdTV.setText(word.getMSutra_id());
sutraTV.setText(word.getMSutras());
vrittiTV.setText(word.getMVritti());
}
//*********** DATABASE OPENING
db = DictionaryDB.getInstance(this.getActivity());
}
private void WordCheck() {
if (word.mStatus != null && word.mStatus.equals(DictionaryDB.BOOKMARKED)) {
fabBtn.setImageResource(R.drawable.cards_heart);
} else {
fabBtn.setImageResource(R.drawable.cards_heart_white);
}
fabBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
bookMarkWord(word, fabBtn);
}
});
}
}
Error im getting
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.sanskrit.mysearcher.models.Astadhyayi.getMSutras()' on a null object reference
at com.sanskrit.mysearcher.fragments.TermThreeDetailsFragment.onCreateView(TermThreeDetailsFragment.java:69)
From the current given information, I think you should do something like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
word = new Astadhyayi(Parcel.obtain());
Bundle bundle = this.getArguments();
if (bundle != null) {
word = bundle.getParcelable("allData");
}
View view = inflater.inflate(R.layout.show_three_details, container, false);
view.findViewById(R.id.tvSutra).setTransitionName(word.getMSutras());
return view;
}
Again, I am not sure what getMSutras() actually returns and if it's right to use that here.

How do I fix Fragment already added in my code?

I open a dialog fragment from A fragment, and when the dialog fragment is closed,
I want to switch from A fragment to B fragment at the same time.
But I keep getting Fragment already added error.
I am using show() instead of replace() to change the screen.
Fragment already added error was easily solved on the web, but
I don't work out weird.
Probably there is a problem with my code, please let me know where the problem is.
MainActivity.java
public class MainActivity extends AppCompatActivity {
BottomNavigationView bottomNav;
FragmentManager fm;
FragmentTransaction transaction;
Fragment curFrag;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottomNav = findViewById(R.id.bottom_nav);
bottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
fm = getSupportFragmentManager();
transaction = fm.beginTransaction();
curFrag = fm.getPrimaryNavigationFragment();
String tag = String.valueOf(item.getItemId());
int id = item.getItemId();
if(curFrag != null) {
transaction.hide(curFrag);
}
Fragment fragment = fm.findFragmentByTag(tag);
if(fragment == null) {
if(id == R.id.list)
fragment = new WorkoutListFragment();
transaction.add(R.id.content_layout, fragment, tag);
}
else {
transaction.show(fragment);
}
transaction.setPrimaryNavigationFragment(fragment);
transaction.setReorderingAllowed(true);
transaction.commitNow();
return true;
}
});
}
// Method for screen switching
public void onFragmentChanged() {
// transaction = fm.beginTransaction();
String tag = "WriteRoutine";
curFrag = fm.getPrimaryNavigationFragment();
if (curFrag != null) {
transaction.hide(curFrag);
}
Fragment fragment = fm.findFragmentByTag(tag);
if (fragment == null) {
fragment = new WriteRoutineFragment();
fragment.setArguments(curFrag.getArguments());
transaction.add(R.id.content_layout, fragment, tag);
} else {
transaction.show(fragment);
}
transaction.setReorderingAllowed(true);
transaction.commit();
}
}
WorkoutListFragment.java (A Fragment)
public class WorkoutListFragment extends Fragment {
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
getParentFragmentManager().setFragmentResultListener("result", this, new FragmentResultListener(){
#Override
public void onFragmentResult(#NonNull String requestKey, #NonNull Bundle result) {
if(result != null)
WorkoutListFragment.this.setArguments(result);
titleData = result.getStringArrayList("title");
}
});
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.activity_workout_list, container, false);
initViews(rootView);
((AppCompatActivity) getActivity()).setSupportActionBar((toolbar));
return rootView;
}
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, #NonNull MenuInflater inflater) {
menu.clear();
inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.record_item_add, menu);
}
#Override // open dialog
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
BodyPartDialogFragment dialog = new BodyPartDialogFragment();
dialog.show(getActivity().getSupportFragmentManager(), "BodyPartDialog");
return true;
}
}
DialogFragment.java
public class BodyPartDialogFragment extends DialogFragment {
Button startBtn;
ArrayList<String> bodypart_strData;
int selectedNum;
final static String TAG = "DialogFragment";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_body_part_dialog, null);
startBtn = view.findViewById(R.id.check);
// A D D
startBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(selectedNum == 0){
Toast.makeText(getContext(), "Plaese select", Toast.LENGTH_SHORT).show();
}
else {
MainActivity activity = (MainActivity) getActivity();
Bundle result = new Bundle();
result.putStringArrayList("title", bodypart_strData);
getParentFragmentManager().setFragmentResult("result", result);
activity.onFragmentChanged();
dismiss();
}
}
});
return view;
}
Upon testing your code, you'll just need to reinstantiate the transaction object before adding/replacing your fragment.
So, you need to add below in onFragmentChanged():
transaction = getSupportFragmentManager().beginTransaction();
And here it is:
// Method for screen switching
public void onFragmentChanged() {
String tag = "WriteRoutine";
transaction = getSupportFragmentManager().beginTransaction(); // <<< THE CHANGE IS HERE
curFrag = fm.getPrimaryNavigationFragment();
if (curFrag != null) {
transaction.hide(curFrag);
}
Fragment fragment = fm.findFragmentByTag(tag);
if (fragment == null) {
fragment = new WriteRoutineFragment();
fragment.setArguments(curFrag.getArguments());
transaction.add(R.id.content_layout, fragment, tag);
} else {
transaction.show(fragment);
}
transaction.setReorderingAllowed(true);
transaction.commit();
}

How to handle configuration change for fragment with view model

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.

Strange behavior of OnItemClickListener inside RecyclerView inside Fragment

Need help with android app (java)
My app starts with SplashActivity. During it I`m getting json via retrofit request and after successfull response I fill my DB
SplashActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
ISplashInteractor splashInteractor = new SplashInteractor();
moviePresenter = new MoviePresenter(this, splashInteractor);
moviePresenter.initDB();
}
after DB successfully loaded automatically starts MovieListActivity
public class MovieListActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_list);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment allMoviesFragment = new AllMoviesFragment();
String tag = "MovieList";
transaction.replace(R.id.main_container, allMoviesFragment, tag);
transaction.commit();
}
}
and at once list of movies loads inside inner fragment AllMoviesFragment(inside recyclerView). till this point everything is ok.
now I set onRecyclerViewItemClickListener - it must open another fragment inside MovieListActivity but instead of this - my app restarts from begining and I observe loading of SpalshActivity again(I put progressbar during request) and again my RecyclerView...
my RecyclerViewAdapter
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private List<MovieDetails> movieList;
private OnRecyclerViewItemClickListener onRecyclerViewItemClickListener;
public RecyclerViewAdapter(List<MovieDetails> movieList) {
this.movieList = movieList;
}
public void setOnRecyclerViewItemClickListener(OnRecyclerViewItemClickListener onRecyclerViewItemClickListener){
this.onRecyclerViewItemClickListener = onRecyclerViewItemClickListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.simple_selectable_list_item, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
MovieDetails movieDetails = (movieList.get(position));
holder.name.setText(movieDetails.getTitle());
holder.year.setText(String.valueOf(movieDetails.getReleaseYear()));
}
#Override
public int getItemCount() {
if (movieList == null)
return 0;
return movieList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
TextView name;
TextView year;
public ViewHolder(View itemView) {
super(itemView);
name = itemView.findViewById(R.id.movie_name);
year = itemView.findViewById(R.id.release_year);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(onRecyclerViewItemClickListener != null){
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION){
onRecyclerViewItemClickListener.onRecyclerViewItemClick(position);
}
}
}
});
}
}
public interface OnRecyclerViewItemClickListener {
void onRecyclerViewItemClick(int position);
}
}
my AllMoviesFragment
public class AllMoviesFragment extends Fragment implements RecyclerViewAdapter.OnRecyclerViewItemClickListener {
private static final String CURR_MOVIE = "Current Movie";
private static final String TAG = "MSApp";
List<MovieDetails> movieList;
RecyclerView recyclerView;
public AllMoviesFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
movieList = App.getAppInstance().getDatabaseInstance().getMovieDao().getAllMovies();
movieList.sort(new Comparator<MovieDetails>() {
#Override
public int compare(MovieDetails o1, MovieDetails o2) {
return o2.getReleaseYear() - o1.getReleaseYear();
}
});
View resultView = inflater.inflate(R.layout.fragment_all_movies, container, false);
recyclerView = resultView.findViewById(R.id.recycler_view);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(movieList);
adapter.setOnRecyclerViewItemClickListener(AllMoviesFragment.this);
recyclerView.setAdapter(adapter);
return resultView;
}
#Override
public void onRecyclerViewItemClick(int position) {
MovieDetails choosenMovie = movieList.get(position);
FragmentManager fragmentManager = getFragmentManager();
Fragment movieDetailsFragment = new MovieDetailsFragment();
Bundle args = new Bundle();
args.putParcelable(CURR_MOVIE, choosenMovie);
movieDetailsFragment.setArguments(args);
String tag = "MovieDetails";
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, movieDetailsFragment, tag);
transaction.addToBackStack(tag);
transaction.commit();
}
}
sorry for long post. I dont know how to cut it
I use App class for db access if it is important
#AkakiKapanadze
you was almost right
I didnot see the error message because it disappeared less 1 second
and class MovieDetailsFragment
after I remove binder of ButterKnife all work... I dont know WHY - I always use Butterknife inside Fragments

Fragments - tag, condition and show

I will be very grateful for the analysis of these lines of code, because I do not understand the relationship between them. Especially if I
I will change tags to 2 different tags, nothing changes in the application. In addition, if the condition if is removed, there are also no changes. In the comments I have a brief translation, I am still unable to understand these three lines.
Fragment fr = manager.findFragmentByTag("AddCity");
What role does this condition fulfill?
if (fr != null) {// if ???
manager.beginTransaction().remove(fr).commit();
}
And:
fr2.show(manager, "AddCity");
This is the whole code snippet
/*
I create a variable manager, and then I get a FragmentManager and assign it to the variable manager,
thanks to the variable manager, I can run actions on fragments
*/
FragmentManager manager = getSupportFragmentManager();
Fragment fr = manager.findFragmentByTag("AddCity");//I created fr variable and ???
Fragment1 fr1 = (Fragment1)
manager.findFragmentById(R.id.list); // I created fr1 variable and assigned fragment list to the variable fr1
if (view.equals(b1)) {
if (fr != null) {// if ???
manager.beginTransaction().remove(fr).commit();//Creates a new transaction to change fragments at runtime, removes an existing fragment, plans to commit the transaction.
}
Fragment2 fr2 = new Fragment2();//Created object Fragment2
fr2.show(manager, "AddCity");//Display the dialog box by adding the fragment to the given FragmentManager.
}
EDIT:
This is my MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button b1, b2;
static int itemSelected;
static boolean isSelected;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b1 = findViewById(R.id.button1);
b2 = findViewById(R.id.button2);
b1.setOnClickListener(this);
b2.setOnClickListener(this);
}
#Override
public void onClick(View view) {
FragmentManager manager = getSupportFragmentManager();//
Fragment fr = manager.findFragmentByTag("addCity");
Fragment1 fr1 = (Fragment1)
getSupportFragmentManager().findFragmentById(R.id.list);
if (view.equals(b1)) {
if (fr != null) {
manager.beginTransaction().remove(fr).commit();
}
Fragment2 fr2 = new Fragment2();
fr2.show(manager, "");
}
if (view.equals(b2)) {
if (!fr1.cities.isEmpty()) {
if (isSelected) {
fr1.cities.remove(itemSelected);
fr1.adapter.notifyDataSetChanged();
itemSelected = 0;
isSelected = false;
fr1.getListView()
.setSelector(android.R.color.transparent);
} else {
Toast.makeText(this, "Select city to be deleted",
Toast.LENGTH_LONG).show();
}
}
}
}
}
Fragment1:
public class Fragment1 extends ListFragment {
ArrayList<String> cities = new ArrayList<>();
ArrayAdapter<String> adapter;
String name;
public Fragment1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_fragment1,
viewGroup, false);
adapter = new ArrayAdapter<>(getActivity(),
android.R.layout.simple_list_item_1, cities);
setListAdapter(adapter);
return view;
}
public void onListItemClick(ListView listView, View view,
int position, long id) {
MainActivity.itemSelected = position;
MainActivity.isSelected = true;
getListView().setSelector(android.R.color.holo_blue_dark);
}
}
Fragment2:
public class Fragment2 extends DialogFragment {
EditText et;
public Fragment2() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_fragment2, viewGroup, false);
}
public void onViewCreated(View view, Bundle savedInstanceState) {
et = view.findViewById(R.id.editText);
Button b = view.findViewById(R.id.button);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String country = et.getText().toString();
Fragment1 fr1 = (Fragment1)
getFragmentManager().findFragmentById(R.id.list);
if (!country.equals("")) {
fr1.cities.add(country);
fr1.adapter.notifyDataSetChanged();
}
getActivity().getSupportFragmentManager().beginTransaction()
.remove(Fragment2.this).commit();
}
});
}
}
You are adding another fragment in the same name. Can you try changing the name to something else and try?
Like
fr2.show(manager, "Add District");
so that you can find the difference.
Adding a fragment
Fragment fr2 = new Fragment();
FragmentManager manger = getSupportFragmentManager();
FragmentTransaction ft = manger.beginTransaction();
ft.add(R.id.placeHolder, fr2,tag);
ft.commitAllowingStateLoss();
if(fr2.isAdded()){
fr2.show(manager, "");
}
Before calling show, you have to add the fragment.

Categories