Displaying data getting fetched asynchronously in a RecyclerView in Fragment - android

I am trying to load the data list asynchronously and showing it on RecyclerView in fragments. However, the same implementation works for Activity class but fails for Fragment:
public class ItemThreeFragment extends Fragment {
String email;
private CompositeSubscription mSubscriptions;
HistoryAdapter historyAdapter;
RecyclerView recyclerView;
public static ItemThreeFragment newInstance() {
ItemThreeFragment fragment = new ItemThreeFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
email = ((BaseApplication) getActivity().getApplication()).getEmail();
mSubscriptions = new CompositeSubscription();
getUserHistory(email);
}
private void getUserHistory(String email) {
mSubscriptions.add(NetworkUtil.generic().getUserCheckinInfo(email)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(this::handleCheckInInfoResponse,this::handleError));
}
private void handleCheckInInfoResponse(List<Checkin> checkins) {
System.out.println(checkins);
historyAdapter = new HistoryAdapter(this.getActivity(), checkins);
recyclerView.setAdapter(historyAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
}
private void handleError(Throwable throwable) {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_item_three, container, false);
recyclerView = (RecyclerView) rootView.findViewById(R.id.historyList);
return rootView;
}
}
Any kind of suggestions will be highly appreciated.

try to set the adapter in onCreateView() instead of onCreate.
Check for data
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(historyAdapter);
Use these two lines onCreateView after you have fetched the data.

Related

How to calling Firestore Database in Fragment using FirebaseUi?

So I'm gonna calling my database from Firestore using Recycler View with FirebaseUi in my fragment but somehow every time I opened my app, the app stop working.
Here's my Fragment Contains Firestore Database.
public class Fragment_HomeSpot extends Fragment {
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference spotRef = db.collection("Spot");
private SpotAdapter adapter;
#SuppressLint("ResourceType")
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.id.recyclerview_layout,container,false);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setUpRecyclerView();
}
private void setUpRecyclerView() {
Query query = spotRef.orderBy("",Query.Direction.DESCENDING);
FirestoreRecyclerOptions<Spot> options = new FirestoreRecyclerOptions.Builder<Spot>()
.setQuery(query, Spot.class)
.build();
adapter = new SpotAdapter(options);
RecyclerView recyclerView = Objects.requireNonNull(getView()).findViewById(R.id.recyclerview_layout);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(adapter);
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
}
onCreate() happens before onCreateView(), so when you call getView() in setUpRecyclerView(), you get null back - you haven't inflated the view yet.
Instead, you should put your setUpRecyclerView() method within onViewCreated(), at which time getView() will return the view you inflated in onCreateView():
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
setUpRecyclerView();
}

RecyclerView with sqlite db working in activity but not working in fragments

I am the beginner in android
I have found many answers of a similar question but no answer unfortunately worked for me
I am using recylcerView using card view to show student data .I am taking Data from My sqlite db.
My code works fine in activity but because of navigation drawer i put it in a fragment and it is showing blank.
here is my activity and fragment code.
MainActivity
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private PersonDBHelper dbHelper;
private MyCustomAdapter adapter;
private String filter = "";
TextView textView;
public static int navItemIndex = 0;
Toolbar toolbar;
private DrawerLayout mDrawerLayout;
FloatingActionButton button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.person_list);
/* toolbar=findViewById(R.id.toolbar);
setSupportActionBar(toolbar);*/
mDrawerLayout=findViewById(R.id.drawer_layout);
NavigationView navigationView=findViewById(R.id.nav_view);
mRecyclerView = (RecyclerView)findViewById(R.id.recycler_view);
textView=findViewById(R.id.empty_view);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
//populate recyclerview
populaterecyclerView(filter);
button=findViewById(R.id.fab_add);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
goToAddUserActivity();
}
});
}
private void populaterecyclerView(String filter) {
dbHelper = new PersonDBHelper(this);
adapter = new MyCustomAdapter(dbHelper.peopleList(filter), this, mRecyclerView);
mRecyclerView.setAdapter(adapter);
}
private void goToAddUserActivity(){
Intent intent = new Intent(MainActivity.this, AddRecordActivity.class);
startActivity(intent);
}
#Override
protected void onResume() {
super.onResume();
adapter.notifyDataSetChanged();
}
this is working fine but for the fragment i did following changes
StudentListFragment()
ublic class StudentListFragment extends Fragment {
private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private PersonDBHelper dbHelper;
private MyCustomAdapter adapter;
FloatingActionButton button;
private String filter = "";
View rootView;
#RequiresApi(api = Build.VERSION_CODES.M)
public static StudentListFragment newInstance(){
StudentListFragment studentListFragment = new StudentListFragment();
Bundle args=new Bundle();
studentListFragment.setArguments(args);
return studentListFragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
rootView=inflater.inflate(R.layout.person_list,container,false);
mRecyclerView=rootView.findViewById(R.id.recycler_view);
dbHelper = new PersonDBHelper(getContext());
adapter = new MyCustomAdapter(dbHelper.peopleList(filter), getContext(), mRecyclerView);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
button=rootView.findViewById(R.id.fab_add);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
goToAddUserActivity();
}
});
return rootView;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setRetainInstance(false);
ensureList();
}
private void goToAddUserActivity() {
Intent intent = new Intent(getActivity(), AddRecordActivity.class);
startActivity(intent);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getActivity().setTitle("StudentList");
}
public void ensureList(){
if (dbHelper != null) {
return;
}
View root = getView();
if (root == null) {
throw new IllegalStateException("Content view not yet created");
} }
}
i am calling this fragment in navigation drawer code is working but not displaying any data. If i put this fragment first in navigation drawer menu means when navigation drawer activity starts this fragment will get open.In such case it is displaying my cards(my data) but if i switch to other fragment and return back to this fragment it is showing blank
In fragment, onCreateView() method, please inflate your root view and return it immediately, do not do anything else.
Implement your logic to onViewCreated(). something like this :
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
rootView=inflater.inflate(R.layout.person_list,container,false);
return rootView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getActivity().setTitle("StudentList");
mRecyclerView=view.findViewById(R.id.recycler_view);
dbHelper = new PersonDBHelper(getContext());
adapter = new MyCustomAdapter(dbHelper.peopleList(filter), getContext(), mRecyclerView);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
button=view.findViewById(R.id.fab_add);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
goToAddUserActivity();
}
});
}
could you please try this. And make sure you have items in the list.

How can I reuse my fragment's code?

I'm writing an Android application with ViewPager. My ViewPager contains two Fragments. In each fragment are located two receclerViews to show different LiveData lists of items from Database (I'm using Room)
The code for BaseFragment
public class BaseFragment extends Fragment {
private RecyclerView recyclerView;
private NewsAdapter adapter;
public ViewModel mViewModel;
public BaseFragment() {
// Required empty public constructor
}
#Override
public void onCreate(#Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(ViewModel.class);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View mView = inflater.inflate(R.layout.fragment_feeds, container, false);
recyclerView = mView.findViewById(R.id.feeds_recycler_view);
return mView;
}
#Override
public void onActivityCreated(#Nullable final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setUpRecyclerView();
mViewModel.getAllNewsEntities()
.observe(this, allNewsEntities -> {
NewsEntityUtilCallback productDiffUtilCallback =
new NewsEntityUtilCallback(adapter.getNewsItems(), allNewsEntities);
DiffUtil.DiffResult newsEntitiesDiffResult = DiffUtil.calculateDiff(productDiffUtilCallback);
adapter.setNewsItems(allNewsEntities);
newsEntitiesDiffResult.dispatchUpdatesTo(adapter);
});
}
protected void setUpRecyclerView() {
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
ItemClickListener onClickListener = (v, position) -> {
String url = adapter.getNewsItems().get(position).getLink();
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
if (browserIntent.resolveActivity(getContext().getPackageManager()) != null) {
startActivity(browserIntent);
}
};
adapter = new NewsAdapter(getContext(), onClickListener);
recyclerView.setAdapter(adapter);
}
}
Look closely at this code section:
mViewModel.getAllNewsEntities()
.observe(this, allNewsEntities -> {
NewsEntityUtilCallback productDiffUtilCallback =
new NewsEntityUtilCallback(adapter.getNewsItems(), allNewsEntities);
DiffUtil.DiffResult newsEntitiesDiffResult = DiffUtil.calculateDiff(productDiffUtilCallback);
adapter.setNewsItems(allNewsEntities);
newsEntitiesDiffResult.dispatchUpdatesTo(adapter);
});
}
Here I'm going to observe different LiveData queries in each Fragment(in the second Fragment it's mViewModel.getAllBookmarkedNewsEntities()).The other things my code will be equals (the same lifecycles methods, the same RecyclerView). So could give me advice about the best possible design principle to refactor my code. I don't want simply to copy my code in another Fragment class just because of one line
Just extends the BaseFragment and override onActivityCreated method. Something like this:
public class ReuseBaseFragment extends BaseFragment {
#Override
public void onActivityCreated(#Nullable final Bundle savedInstanceState) {
//Your new code here
}
}

unable to retrieve data from Firebase using Fragments in Android Studio

Hy! I am trying to retrieve data from Firebase but unable to show the pictures and names of categories on the fragment layout. I can't understand whether its Firebase error or Layout error because on selecting fragment imageview or textview are also not been shown. This is the code from categories fragment in which recyclerview is used in fragment layout XML file.
public class CategoriesFragment extends Fragment {
View myfragment;
RecyclerView listCategory;
RecyclerView.LayoutManager layoutManager;
FirebaseRecyclerAdapter<Category,CategoryViewHolder> adapter;
FirebaseDatabase database;
DatabaseReference categories;
public static CategoriesFragment newInstance(){
CategoriesFragment categoriesFragment = new CategoriesFragment();
return categoriesFragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
database = FirebaseDatabase.getInstance();
categories = database.getReference("Category");
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
myfragment = inflater.inflate(R.layout.fragment_categories,container,false);
listCategory = (RecyclerView)myfragment.findViewById(R.id.listcategory);
listCategory.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(container.getContext());
listCategory.setLayoutManager(layoutManager);
loadCategories();
return myfragment;
}
private void loadCategories() {
adapter = new FirebaseRecyclerAdapter<Category, CategoryViewHolder>(
Category.class,
R.layout.category_layout,
CategoryViewHolder.class,
categories
) {
#Override
protected void populateViewHolder(CategoryViewHolder viewHolder, final Category model, int position) {
viewHolder.category_name.setText(model.getName());
Picasso.with(getActivity())
.load(model.getImage())
.into(viewHolder.category_image);
viewHolder.setItemClickListener(new ItemClickListener() {
#Override
public void onClick(View view, int position, boolean isLongClick) {
Toast.makeText(getActivity(),String.format("%s|%s",adapter.getRef(position).getKey(),model.getName()),Toast.LENGTH_LONG).show();
}
});
}
};
adapter.notifyDataSetChanged();
listCategory.setAdapter(adapter);
}`

How to convert Fragment code to Activity code

I want to convert this fragment to activity please help me !
public class MenuCategoryFragment extends Fragment {
private static final String TAG = MenuCategoryFragment.class.getSimpleName();
private RecyclerView recyclerView;
public MenuCategoryFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
getActivity().setTitle(getString(R.string.manu_categories));
View view = inflater.inflate(R.layout.fragment_menu_category, container, false);
recyclerView = (RecyclerView)view.findViewById(R.id.food_menu);
GridLayoutManager mGrid = new GridLayoutManager(getActivity(), 2);
recyclerView.setLayoutManager(mGrid);
recyclerView.setHasFixedSize(true);
return view;
}
}
This is your Activity Class.
public class YourActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_menu_category);
recyclerView = (RecyclerView) findViewById(R.id.food_menu);
GridLayoutManager mGrid = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(mGrid);
recyclerView.setHasFixedSize(true);
}
}
One last thing, make sure you declare your "Activity" class in "AndroidMenifest".

Categories

Resources