I used a recyclerView on my app to display all files from an external storage. Until I changed it, it worked fine when it was implemented in the "MainActivity.java".
Now, I want my app to have a "BottomNavigationBar"; in order to do that, I use fragments. The problem is the app crashes when I touch the specific item from the menu (the one containing the RecyclerView).
I changed all the "this" method to ".getActivity()" but it crashed anyways. I changed it to ".getActivity().getApplicationContext()" but it still crashed.
I'm sorry, my computer does not support hardware acceleration so I can't properly show what the error is. Instead, I have attached a debugger to my connected phone and set up breakpoints. The debugger highlighted the line "RecyclerView recyclerView = getView().findViewById(R.id.recyclerview);" when the app crashed.
Here's the fragment code:
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_records, container, false);
}
private static final int PERMISSION_REQUEST = 1000;
private ArrayList<String> mNames = new ArrayList<>();
public static ArrayList<String> NbFiles = new ArrayList<>();
public ArrayList<String> PathFiles = new ArrayList<>();
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Check if we have the permission to read storage
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
//We don't have the permission, so request it.
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST);
}
//We already have permission
else {
permissionExists();
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PERMISSION_REQUEST) {
if (resultCode == RESULT_OK) {
permissionExists();
} else {
//handle error
}
}
}
private void initRecyclerView() {
RecyclerView recyclerView = getView().findViewById(R.id.recyclerview);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(mNames, getActivity().getApplicationContext(), (RecyclerViewAdapter.OnNoteListener) this);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
}
private void permissionExists() {
String path = Environment.getExternalStorageDirectory().toString() + "/Rapture";
File directory = new File(path);
boolean success = true;
if (!directory.exists()) {
success = directory.mkdirs();
}
if (success) {
File[] arrayFiles = directory.listFiles();
for (File file : arrayFiles) {
mNames.add(file.getName());
PathFiles.add(file.getPath());
NbFiles.add(file.getName());
}
}
initRecyclerView();
}
}
[Let me know if you need more code]
How can I fix this ?
RecyclerView recyclerView = getView().findViewById(R.id.recyclerview);
Instead of getView(), you need to use the view inflated in onCreateView
So,
RecyclerView recyclerView;
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_records, container, false);
recyclerView = v.findViewById(R.id.recyclerview);
return v;
}
If you want, you can then populate the RecyclerView (or make it visible, or whatever) in initRecyclerView()
Change your code to this-
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_records, container, false);
initRecyclerView(view);
return view;
}
private void initRecyclerView(View view) {
RecyclerView recyclerView = view.findViewById(R.id.recyclerview);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(mNames, getActivity().getApplicationContext(), (RecyclerViewAdapter.OnNoteListener) this);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
}
try this
getActivity() instance of getView()
RecyclerView recyclerView = getView().findViewById(R.id.recyclerview);
instance of
RecyclerView recyclerView = getActivity().findViewById(R.id.recyclerview);
Move below code for handling permission onActivityCreated
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
//We don't have the permission, so request it.
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST);
}
//We already have permission
else {
permissionExists();
}
}
In Fragment, you can initialize your view in onViewCreated
// This event is triggered soon after onCreateView().
// Any view setup should occur here. E.g., view lookups and attaching view listeners.
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// Setup any handles to view objects here
initRecyclerView(view);
}
Change your initRecyclerView() like below,
private void initRecyclerView(View v) {
RecyclerView recyclerView = v.findViewById(R.id.recyclerview);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(mNames, getActivity().getApplicationContext(), (RecyclerViewAdapter.OnNoteListener) this);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
}
It will shows fragment page without blank,
For more clarification about life cycle of Fragment, refer this
Remove the onCreate mewthod and move the logic into onCreateView
Here the issue is your recyclerView initializes by calling getActivity() but the problem is that the activity does not exist until onActivityCreated() is called.
So it's crashing. Move all of that code inside onCreate() to onActivityCreated() and it should work fine.
Related
I'm trying to add recyclerview in my fragment but I'm getting error when I click on navigation drawer item.
Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
at com.example.myapplication.fragment.Books.onCreate(Books.java:45)
How to resolve error or suggest tutorial to load json data in fragment using recyclerview. with click event on recyclerview. on click item open new fragment with data.
This is my code
public class Books extends Fragment {
private BooksModel booksViewModel;
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private List<BooksModel> bookLists;
// Context context;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
recyclerView = (RecyclerView) getView().findViewById(R.id.recyclerViewBook); //Line 45 Error
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
bookLists = new ArrayList<>();
for(int i=0; i<=10; i++){
BooksModel bookList = new BooksModel(
"",
"Title " + (i + 1),
"This is Auther"
);
bookLists.add(bookList);
adapter = new BooksAdapter(bookLists,this);
recyclerView.setAdapter(adapter);
}
}
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
booksViewModel =
new ViewModelProvider(this).get(BooksModel.class);
View root = inflater.inflate(R.layout.fragment_books, container, false);
final TextView textView = root.findViewById(R.id.text_book );
booksViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
textView.setText(s);
}
});
return root;
}
}
onCreate() runs before onCreateView(). You should move all of that code to onViewCreated(), which passes you the View directly (meaning you don't have to call getView() at all).
Can someone tell me why the submitList() method can't be accessed in the following code? Similar code is working fine in another test app, although that's in an Activity.
public class MyFFBooksFragment extends Fragment {
private int currentBook;
private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private GamebookViewModel gamebookViewModel;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable
ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.myffbooks_fragment, container, false);
mLayoutManager = new LinearLayoutManager(getActivity());
final ArrayList<BookItem> bookList = new ArrayList<>();
final BookItemAdapter maAdapter = new BookItemAdapter(bookList);
mRecyclerView = view.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setAdapter(maAdapter);
gamebookViewModel = ViewModelProviders.of(this).get(GamebookViewModel.class);
gamebookViewModel.getAllGamebooks().observe(this, new Observer<List<Gamebook>>() {
#Override
public void onChanged(#Nullable List<Gamebook> gamebooks) {
maAdapter.submitList(bookList);
}
});
return view;
}
}
Perhaps you should not use it in onCreateView(). Try use call method that triggers observation of VM after an Activity had been created, near onStart(). Maybe it will help.
When a new page is available, we call submitList() method of the PagedListAdapter class
override fun onStart() {
super.onStart()
gamebookViewModel.callFunc()
}
Also as I understand, you call getAllGamebooks() which triggers some actions and return you LiveData<*> and you subscribe on it with observe(). I recommend you to separate this on 2 methods:
subscribe
action
Use PagedList instead of list like below:
gamebookViewModel.getAllGamebooks().observe(this, new Observer<PagedList<Gamebook>>() {
#Override
public void onChanged(#Nullable PagedList<Gamebook> gamebooks) {
maAdapter.submitList(bookList);
}
});
And in your viewmodel too.
Found the problem. My adapter wasn't extending ListAdapter, so no wonder it couldn't find the submitList() method. Rookie error.
Hey guys I really need your help. I've spent like 5 days trying to get my recyclerview to update only when the user presses OK on a dialogbox, that appears from the menu actionbar. I've tried every possible method I could think of, every method I've seen on stackoverflow, YouTube, etc. and none of them worked for me.
How do I get the recyclerview in a fragment to update after dialogbox closes? I know there are similar questions regarding updating the menu, and (recyclerviews with dialogfragments), but none of them have a combination.
Out of the countless attempts, the current code configuration posted below isn't causing any errors, however, the recyclerview remains blank. The closest attempt I had to finding a solution, was creating an adapter and setting up the recycler in onOptionsItemSelected. But obviously, it updates only when the user clicks the button, and the initial click would create a blank recyclerview.
Fragment:
(There's a lot of repeated commented code from different attempts)
public class ExerciseRoutine extends Fragment implements ExerciseRoutine_Dialog.RoutineDialogListener{
private String Routine_name, Routine_split;
private ArrayList<ExerciseRoutine_Information> Routine_information = new ArrayList<>();
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
#Override
public void sendInput(String name, String split, RecyclerView.Adapter DialogAdapter) {
Routine_name = name;
Routine_split = split;
adapter = DialogAdapter;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.exercise_routine_fragment, container, false);
//Report that this fragment would like to participate in populating the options menu by
//receiving a call to onCreateOptionsMenu(Menu, MenuInflater) and related methods.
//If true, the fragment has menu items to contribute.
setHasOptionsMenu(true);
recyclerView = view.findViewById(R.id.ExerciseRoutine_Recycler);
//BuildRecyclerView();
//recyclerView.setHasFixedSize(true); //If the Recyclerview is static
/*Routine_information.add(new ExerciseRoutine_Information(Routine_name, Routine_split));
recyclerView = view.findViewById(R.id.ExerciseRoutine_Recycler);
//recyclerView.setHasFixedSize(true); //If the Recyclerview is static
layoutManager = new LinearLayoutManager(getActivity());
adapter = new ExerciseRoutineAdapter(Routine_information);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);*/
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.exercise_routine_menu, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case R.id.action_addRoutine:
ExerciseRoutine_Dialog routineDialog = new ExerciseRoutine_Dialog();
routineDialog.setTargetFragment(ExerciseRoutine.this, 1);
routineDialog.show(getFragmentManager(), "Routine Dialog");
//Routine_information.add(new ExerciseRoutine_Information(Routine_name, Routine_split));
BuildRecyclerView();
//adapter.notifyItemInserted(Routine_information.size());
//if(!Routine_name.equals("") && !Routine_split.equals("")) {
//}
}
return super.onOptionsItemSelected(item);
}
public void BuildRecyclerView(){
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
public void BuildAdapter(){
//adapter = new ExerciseRoutineAdapter(getContext(),Routine_information);
adapter.notifyItemInserted(Routine_information.size());
}
}
My Dialog Fragment:
public class ExerciseRoutine_Dialog extends DialogFragment{
private TextView ActionOK, ActionCANCEL;
private EditText Routine_name, Routine_split;
private RoutineDialogListener activityCommander;
private ArrayList<ExerciseRoutine_Information> Routine_information = new ArrayList<>();
private RecyclerView.Adapter adapter;
public interface RoutineDialogListener{
void sendInput(String name, String split, RecyclerView.Adapter DialogAdapter);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try{
activityCommander = (RoutineDialogListener) getTargetFragment();
}catch(ClassCastException e){
throw new ClassCastException(context.toString() + "Must Implement RoutineDialogListener");
}
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.exercise_routine_dialog, container, false);
Routine_name = view.findViewById(R.id.ExerciseRoutine_DialogNameInput);
Routine_split = view.findViewById(R.id.ExerciseRoutine_DialogSplitInput);
ActionOK = view.findViewById(R.id.ExerciseRoutine_DialogAction_OK);
ActionCANCEL = view.findViewById(R.id.ExerciseRoutine_DialogAction_CANCEL);
//recyclerView = view.findViewById(R.id.ExerciseRoutine_Recycler);
ActionCANCEL.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getDialog().dismiss();
}
});
ActionOK.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String name = Routine_name.getText().toString();
String split = Routine_split.getText().toString();
if(!name.equals("") && !split.equals("")) {
Routine_information.add(new ExerciseRoutine_Information(name, split));
adapter = new ExerciseRoutineAdapter(getContext(), Routine_information);
activityCommander.sendInput(name, split, adapter);
adapter.notifyItemInserted(Routine_information.size());
}
getDialog().dismiss();
}
});
return view;
}
}
Your current approach seems to be to pass the RecyclerView.Adapter to the DialogFragment and try to insert the new data on-the-spot. I think this is a problematic setup. The dialog's purpose is to offer some means for the users to enter the required data, period. It should not be tasked with the job of managing the RecyclerView or its Adapter because that way your components will be very tightly coupled:
Imagine that first you use a ListView in your implementation, and suddenly someone decides to ban every ListView from your app (maybe for performance reasons) and has you exchange them all for RecyclerViews. Then your approach would force you to change the code for the DialogFragment (it would have to cater to a different type of Adapter). A more loosely coupled implementation would enable you to make changes to one component without having to rewrite too many others.
That's why I won't try to make your code work as-is, instead I'd like to show you another way:
Because the RecyclerView is part of the Fragment's UI, the Fragment is the place where code related to managing the RecyclerView belongs. It is basically possible to have the Adapter as an inner class of the Fragment but I prefer having it as a standalone class if the code gets a little longer, and also because it enforces "decoupling".
Interfaces play a very important part in good architecture, so the DialogFragment will still make use of an interface to send its data. But it's up to the class which actually implements the interface (here: the Fragment) to pass the data to any interested third parties, e.g. the RecyclerView.Adapter (The Adapter in turn could have its own interface to publish important events like clicks on list items).
Having said that, here are some code snippets:
The DialogFragment
public class ExerciseRoutine_Dialog extends DialogFragment {
private EditText Routine_name, Routine_split;
public interface RoutineDialogListener{
/**
* There is some new ExerciseRoutine_Information
*/
void sendInput(String name, String split);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.exercise_routine_dialog, container, false);
Routine_name = view.findViewById(R.id.ExerciseRoutine_DialogNameInput);
Routine_split = view.findViewById(R.id.ExerciseRoutine_DialogSplitInput);
TextView actionOK = view.findViewById(R.id.ExerciseRoutine_DialogAction_OK);
TextView actionCANCEL = view.findViewById(R.id.ExerciseRoutine_DialogAction_CANCEL);
actionCANCEL.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getDialog().dismiss();
}
});
actionOK.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String name = Routine_name.getText().toString();
String split = Routine_split.getText().toString();
if(!name.equals("") && !split.equals("")) {
// just send the input to the main Fragment
RoutineDialogListener listener = getListener();
if(listener != null) {
listener.sendInput(name, split);
}
}
getDialog().dismiss();
}
});
return view;
}
/**
* Tries to find a suitable listener, examining first the hosting Fragment (if any) and then the Activity.
* Will return null if this fails
* #return x
*/
private RoutineDialogListener getListener(){
RoutineDialogListener listener;
try{
Fragment onInputSelected_Fragment = getTargetFragment();
if (onInputSelected_Fragment != null){
listener = (RoutineDialogListener) onInputSelected_Fragment;
}
else {
Activity onInputSelected_Activity = getActivity();
listener = (RoutineDialogListener) onInputSelected_Activity;
}
return listener;
}catch(ClassCastException e){
Log.e("Custom Dialog", "onAttach: ClassCastException: " + e.getMessage());
}
return null;
}
}
The Fragment:
public class ExerciseRoutine extends Fragment implements ExerciseRoutine_Dialog.RoutineDialogListener{
public static final String ROUTINE_DIALOG = "Routine Dialog";
private ArrayList<ExerciseRoutine_Information> routineInformations = new ArrayList<>();
private RecyclerView.Adapter adapter;
public static ExerciseRoutine instance(){
return new ExerciseRoutine();
}
#Override
public void sendInput(String name, String split) {
routineInformations.add(new ExerciseRoutine_Information(name, split));
adapter.notifyItemInserted(routineInformations.size());
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.exercise_routine_fragment, container, false);
setHasOptionsMenu(true);
RecyclerView recyclerView = view.findViewById(R.id.ExerciseRoutine_Recycler);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
adapter = new ExerciseRoutineAdapter(getContext(), routineInformations);
// So far you have a RecyclerView with an empty List.
recyclerView.setAdapter(adapter);
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.exercise_routine_menu, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case R.id.action_addRoutine:
showDialog();
return true;
}
return super.onOptionsItemSelected(item);
}
private void showDialog(){
ExerciseRoutine_Dialog routineDialog = new ExerciseRoutine_Dialog();
routineDialog.setTargetFragment(ExerciseRoutine.this, 1);
routineDialog.show(getFragmentManager(), ROUTINE_DIALOG);
}
}
I have a ListFragment which fetches data from the net using a Loader. I use a new instance of this ListFragment in every page of my ViewPager. It works perfectly, but when I use TabLayout or moves pages quickly, the Fragment keeps loading and does not display the data in the ListView.
When I checked using log messages, I found that the ListFragment skips some lines of code in the onLoadFinished() method. It does not make the ProgressBar invisible. It does add items to Adapter, but it is not being displayed in the ListView. This problem also happens in the first page of the ViewPager.
Is there any specific rule to be followed when using ListFragments in a ViewPager?
Here is the ListFragment class. If you look at the onLoadFinished() method, you can see the lines causing problem:
public class ListViewFragment extends ListFragment
implements LoaderManager.LoaderCallbacks<List<GameNews>> {
public static ListViewFragment newInstance(String url) {
Log.d("ListViewFragment", "newInstance created");
ListViewFragment f = new ListViewFragment();
// Supply url input as an argument.
Bundle args = new Bundle();
args.putString("url", url);
f.setArguments(args);
return f;
}
List<GameNews> TotalNews;
ListView gameListView;
LinearLayout emptyView;
Button retryButton;
ListAdapter adapter ;
private View progressBar;
final private int game_loader = 0;
ArrayList<String> urls = new ArrayList<>();
String mUrlString;
int index;
//LIFE CYCLE OF FRAGMENT
//------------------------------------------------------------------
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUrlString = getArguments().getString("url");
urls.add(mUrlString);
TotalNews = new ArrayList<GameNews>();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_list_view, container, false);
ArrayList<GameNews> gameList = new ArrayList<>();
adapter = new ListAdapter(getActivity(), gameList);
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
emptyView = (LinearLayout)
view.findViewById(R.id.no_internet_view);
progressBar = view.findViewById(R.id.progress_bar);
retryButton = (Button) view.findViewById(R.id.retry_button);
gameListView = getListView();
emptyView.setVisibility(View.INVISIBLE);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setListAdapter(adapter);
//If connected to net start the loader
if (isConnected()) {
getActivity().getSupportLoaderManager().restartLoader(game_loader,
null,
ListViewFragment.this);
}
}
//OVERRIDED METHODS OF LOADERMANAGER
//---------------------------------------------------------------------
#Override
public android.support.v4.content.Loader<List<GameNews>> onCreateLoader(int i, Bundle bundle) {
AdManager manager = new AdManager(getActivity());
return new FragmentLoader(getActivity(), urls, 1000);
}
//HERE IS THE PROBLEM PLEASE FOCUS INSIDE THIS METHOD
//-------------------------------------------------------
#Override
public void onLoadFinished(Loader<List<GameNews>> loader, List<GameNews> games) {
progressBar.setVisibility(View.INVISIBLE); //This line of code is not executed
adapter.clear();
TotalNews.addAll(games);
adapter.addAll(games);//And the listView is not populated
}
//-------------------------------------------------------
#Override
public void onLoaderReset(Loader<List<GameNews>> loader) {
adapter.clear();
}
//REUSABLE METHODS
//------------------------------------------------------------------
//Method checks if there is internet
public boolean isConnected() {
ConnectivityManager manager = (ConnectivityManager)
getActivity().getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo info = manager.getActiveNetworkInfo();
if (info != null && info.isConnected()) {
return true;
}
else {
return false;
}
}
}
Your Fragment class is using the Activity's LoaderManager:
getActivity().getSupportLoaderManager().restartLoader(...);
And each instance is using the same ID in its restartLoader() call:
final private int game_loader = 0;
This means that each Fragment instance was using and restarting the same Loader over and over again, leading to the weird behavior you observed.
The solution is quite simple: use Fragment's local LoaderManager, instead of the Activity's.
getLoaderManager().restartLoader(...);
With this, you don't need to worry about changing the ID in each instance, since Loaders are unique to their Fragment, and the Loader will be properly handled over the Fragment's lifetime, which would likely not have been the case when using the Activity's LoaderManager.
I m have a problem with my RecyclerView. I m trying to populate it with a list of friends names, however when i launch my fragment friends are not loaded. On the other side friends are loaded if i m entering debug mode.
My code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mKinveyClient = KinveyUtils.getClient(getContext());
mFriends = getUserFriends();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_friend_list, container, false);
// Set the adapter
if (view instanceof RecyclerView) {
Context context = view.getContext();
mRecyclerView = (RecyclerView) view;
mRecyclerView.setLayoutManager(new LinearLayoutManager(context));
mRecyclerView.setAdapter(new FriendRecyclerViewAdapter(mFriends));
}
return view;
}
private ArrayList<ArrayMap> getUserFriends() {
return (ArrayList<ArrayMap>) mKinveyClient.user().get(KinveyConstants.FRIENDS);
}
I feel like the friends are loading too slow, but all the needed data should be already in app by this time. Any idea how to fix it?