(Android Studio) Can't use context/getActivity() in Fragment [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 1 year ago.
First of all, I am absolute beginner for this, I'm sorry if this such a dumb mistakes. But I always got this error
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView.setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager)' on a null object referenceat com.example.loginregister.ui.home.HomeFragment$1.onResponse(HomeFragment.java:104)
whenever I tried to run my app. I already changed getActivity() to HomeFragment.this , or getApplicationActivity() but still error, I'm stuck this for a long time because I not really understand how it's work, I hope someone can explain to me how to call context in fragment, here my java
public class HomeFragment extends Fragment {
private RecyclerView rvData;
private RecyclerView.Adapter adData;
private RecyclerView.LayoutManager lmData;
private List<DataModel> listData = new ArrayList<>();
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rvData = getActivity().findViewById(R.id.rv_user);
lmData = new LinearLayoutManager(getActivity(),LinearLayoutManager.VERTICAL,false);
rvData.setLayoutManager(lmData);
retrieveData();
return inflater.inflate(R.layout.fragment_home, container, false);
}
public void retrieveData(){
APIRequestData ardData = RetroServer.connectRetrofit().create(APIRequestData.class);
Call<ResponseModel> showData = ardData.ardRetrieveData();
showData.enqueue(new Callback<ResponseModel>() {
#Override
public void onResponse(Call<ResponseModel> call, Response<ResponseModel> response) {
int code = response.body().getCode();
String message = response.body().getMessage();
Toast.makeText(getActivity(), "Code: "+code+"| Message: "+message, Toast.LENGTH_SHORT).show();
listData = response.body().getData();
adData = new AdapterData(getActivity(),listData);
rvData.setLayoutManager(lmData);
adData.notifyDataSetChanged();
}
#Override
public void onFailure(Call<ResponseModel> call, Throwable t) {
Toast.makeText(getActivity(), "Fail to Retrieve Data", Toast.LENGTH_SHORT).show();
}
});
}
and here is my fragment_home.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_user"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="#layout/card_item"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

use this code
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
rvData = view.findViewById(R.id.rv_user);
return view;
}

As I see your layout is supposedly layout for a fragment. You should edit your code like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.fragment_home.xml, container, false);
rvData = inflate.findViewById(R.id.rv_user);
lmData = new LinearLayoutManager(getActivity(),LinearLayoutManager.VERTICAL,false);
rvData.setLayoutManager(lmData);
retrieveData();
return inflate;
}
If you really need your "context" basically the private fragment variable
private Context context;
Then you may retrieve it in onAttach method somewhat like this:
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
this.context = context;
}
This enables you to use context specific features like getting colors etc.

Related

Using a ArrayAdapter won't work with fragment

I am trying to get an ArrayList from an activity and then display it inside a fragment in a custom adapter. The problem it's that I cannot setAdapter to do so. The error it says the context it's wrong, when I created the Adapter.
Creare_istoricAdapter class:
public class Creare_istoricAdapter extends ArrayAdapter<Creare_istoric> {
private static final String TAG = "Creareistoric_adapter";
private Context mContext;
int mResource;
public Creare_istoricAdapter(#NonNull Context context, int resource, #NonNull ArrayList<Creare_istoric> objects) {
super(context, resource, objects);
mContext = context;
mResource = resource;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
String id_alerta = getItem(position).getId_alerta();
String tip_problema = getItem(position).getTip_problema();
String data_ora= getItem(position).getData_ora();
String stare_problema = getItem(position).getStare_problema();
String descriere = getItem(position).getDescriere();
Creare_istoric istoric = new Creare_istoric(id_alerta, tip_problema, data_ora, stare_problema, descriere);
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
TextView text_tip_alerta_istoric = convertView.findViewById(R.id.text_tip_alerta_istoric);
TextView text_ora_alerta_istoric = convertView.findViewById(R.id.text_ora_alerta_istoric);
TextView text_stare_alerta_istoric = convertView.findViewById(R.id.text_stare_alerta_istoric);
text_tip_alerta_istoric.setText(tip_problema);
text_ora_alerta_istoric.setText(data_ora);
text_stare_alerta_istoric.setText(stare_problema);
return convertView;
}
}
The fragment class:
public class Fragment_alerte_trimise extends Fragment {
public Fragment_alerte_trimise(){}
ListView list_view_alerte_trimise;
ArrayList<Creare_istoric> alerteTrimise= new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View alerte_trimise = inflater.inflate(R.layout.fragment_alerte_trimise,container, false);
return alerte_trimise;
Bundle bundle_trimise;
if (bundle_trimise != null) {
alerteTrimise = bundle_trimise.getParcelableArrayList("alerte_trimise");
}
list_view_alerte_trimise =getView().findViewById(R.id.list_view_alerte_trimise);
Creare_istoricAdapter adapter = new Creare_istoricAdapter(this, R.layout.istoric_alerte_adapter, alerteTrimise);
list_view_alerte_trimise.setAdapter(adapter);
}
}
The problems it's in new Creare_istoricAdapter(this, R.layout.istoric_alerte_adapter, alerteTrimise) , about the context, and is also greyed out, saying it's redundant.
EDIT:
I have changed the code following the answers below, but now when I open the activity that uses the fragment, it does not show the list at all. It's only an blank screen.
The fragment code:
public class Fragment_alerte_trimise extends Fragment {
public Fragment_alerte_trimise(){}
private ListView list_view_alerte_trimise;
ArrayList<Creare_istoric> alerteTrimise= new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View alerte_trimise = inflater.inflate(R.layout.fragment_alerte_trimise,container, false);
return alerte_trimise;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Bundle bundle_trimise = getArguments();
if (bundle_trimise != null) {
alerteTrimise = bundle_trimise.getParcelableArrayList("alerte_trimise");
}
list_view_alerte_trimise =getView().findViewById(R.id.list_view_alerte_trimise);
list_view_alerte_trimise.setAdapter(new Creare_istoricAdapter(getContext(), R.layout.istoric_alerte_adapter, alerteTrimise));
}
}
The way I created the Parceable:
Bundle bundle_trimise = new Bundle();
bundle_trimise.putParcelableArrayList("alerte_trimise", alerteTrimise);
Fragment_alerte_trimise fg = new Fragment_alerte_trimise();
fg.setArguments(bundle_trimise);
I have the ListView created in the layout that's inflated by the onCreateView, but when I use getView().findViewById it says that it may produce 'NullPointerException', and so does the getContext(), which says it might be null
Please try to use getContext() instead of this.
You have to use activity context instead of fragment context this. Instead of using getContext() or getActivity() you should initialize the context on onAttach to avoid NullPointerException. Check below:
private Context activityContext;
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
activityContext = context;
}
#Override
public void onDetach() {
super.onDetach();
activityContext = null;
}
Beside this, you have to return the view inside onCreateView at the very end. Check below:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
....
// use alerte_trimise instead of getView()
list_view_alerte_trimise = alerte_trimise.findViewById(R.id.list_view_alerte_trimise);
//use activityContext instead of this
Creare_istoricAdapter adapter = new Creare_istoricAdapter(activityContext, R.layout.istoric_alerte_adapter, alerteTrimise);
....
return alerte_trimise;
}
In your code, you try to use Bundle after call return. That's why rest of your code is unreachable.
You are using Creare_istoricAdapter in your Fragment_alerte_trimise so it needs context. therefor we can give activity context or application context(beyond the activity level)
Moreover...
getContext() - Returns the context view only current running activity.
getActivity()- Return the Activity this fragment is currently associated with.
getActivity() can be used in a Fragment for getting the parent Activity of the Fragment.
Add this code changes to your code.
getActivity().getApplicationContext()
Use getContext() instead of this. this refers to current object (Fragment), which is not subclass of Context.
Create adapter in onViewCreated(), because getContext() returns null in onCreateView().

null object reference of TextView in Fragment

I have two fragments and a main activity. The first fragment, FriendsFragment (extends ListFragment) is displayed on the screen and when the user clicks an item, the main Activity replaces the FriendsFragment with FeedFragment, then calls a method from FeedFragment to update the textView.
I'm getting an error that the textView object in the FeedFragment class is null even though I instantiate using the findViewById method.
I have looked at related questions and have tried the solutions but nothing is working. I've tried doing getView().findViewById(R.id.feed_view), getActivity().findViewById(R.id.feed_view), and I've tried putting these in onActivityCreated() and onCreateView()
The only thing that worked is writing this code in onActivityCreated():
text = getView().findViewById(R.id.feed_view);
text.setText("some string");
but this is not what I want
FeedFragments.java
public class FeedFragment extends Fragment {
private static String TAG = "Feed Fragment";
private TextView text;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
Log.i(TAG, "Entered FeedFragment.java onActivityCreated()");
super.onActivityCreated(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
Log.i(TAG, "Entered FeedFragment.java onCreateView()");
View v = inflater.inflate(R.layout.fragment_feed, container,false);;
text = v.findViewById(R.id.feed_view);
return v;
}
public void updateDisplay(int position)
{
Log.i(TAG, "FeedFragment.java: updateDisplay()");
text.setText(position);
}
MainActivity.java
// previously declared feedFragment: feedFragment = new FeedFragment();
public void onItemSelected(int position)
{
Log.i(TAG, "Entered onItemSelected(" + position + ")");
fragManager = getFragmentManager();
FragmentTransaction fragTransaction = fragManager.beginTransaction();
fragTransaction.replace(R.id.fragment_container, feedFragment, "feed_fragment");
fragTransaction.addToBackStack(null);
fragTransaction.commit();
feedFragment.updateDisplay(position);
}
fragment_feed.xml
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/feed_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/greeting" />
</ScrollView>
activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
onViewcreated() is being called after updateDisplay() because the system doesn't run it right away.
you need to pass a value to the feedFragment on it's creation and store it in a bundle and retrieve it after the fragment internal code is run by the system.
the way you solve it is like this:
when you instantiate feedFragment you do it like this:
feedFragment = FeedFragment.newInstance(position)
and inside FeedFragment class you should have a static code:
private static final String ARG_PARAM1 = "param1";
public static FeedFragment newInstance(int param1) {
FeedFragment fragment = new FeedFragment();
Bundle args = new Bundle();
args.putInt(ARG_PARAM1, param1);
fragment.setArguments(args);
return fragment;
}
and non static code:
private int mParam1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getInt(ARG_PARAM1);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
Log.i(TAG, "Entered FeedFragment.java onCreateView()");
View v = inflater.inflate(R.layout.fragment_feed, container,false);;
text = v.findViewById(R.id.feed_view);
text.setText(String.valueOf(mParam1));
return v;
}
I wrapped mParam1 in String.valueOf() because when you pass integer to setText it thinks you try to use a Strings.xml resource instead of the number you chose.
also I used very generic variable names. please change them to something meaningful so that your code makes sense.

No view found for id in a new activity

I have created an activity that I am using for barcode scanning. The onCreate looks like this:
public class GradeScreenScanner extends AppCompatActivity implements ZXingScannerView.ResultHandler {
public static final int REQUEST_CAMERA = 1;
protected ZXingScannerView scannerView;
protected FirebaseFirestore db;
protected String scanResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
scannerView = new ZXingScannerView(this);
setContentView(scannerView);
db = FirebaseFirestore.getInstance();
}
}
Once I have a result I am then wanting to launch a new fragment like so:
android.app.FragmentManager fragmentManager = getFragmentManager();
ScreenFragment screenFragment = new ScreenFragment();
screenFragment.db = db;
screenFragment.serialNumberScanned = serialNumberScanned;
fragmentManager.beginTransaction()
.addToBackStack("screen")
.replace(R.id.content_frame, screenFragment)
.commit();
But I get the following error that I am not sure how to deal with:
java.lang.IllegalArgumentException: No view found for id 0x7f08005a (uk.wefix:id/content_frame) for fragment ScreenFragment{6262536 #1 id=0x7f08005a}
Just in case, the fragments onCreate looks like this:
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
myView = inflater.inflate(R.layout.grade_screens_layout, container, false);
return myView;
}
Help appreciated.
#Override
public void setContentView(View view) {
getDelegate().setContentView(view);
}
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/content_frame"/>
Was missing from the xml in the activity view. My error, well spotted Umair
yes , usually when you get No view found for id or nullPointer i suggest you to check:
1-android:id="#+id/
2- findViewById
3- in the java class the variable declaration
in most cases it works ;)
good luck.

Recycler view not showing the views when a background color is setted

Hi I'm new to Android Studio, and I am trying to make a simple recycler view that contains a list of card view. The code runs just fine and every view is rendering fine when I run it, but then I decided to add background color to recycler view than everything just went wrong. The only thing I've changed is setting the background color of the recycler view. By the way, my recycler view lives in a fragment.
Here is what it looked like before I set the background color:
The xml file for the recycler view before change:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="#layout/recycler_view_item" />
</android.support.constraint.ConstraintLayout>
And here is what it looks like now, all I did is setting the background color of the recycler view:
Here is the new xml file:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_green_dark"
tools:listitem="#layout/recycler_view_item" />
</android.support.constraint.ConstraintLayout>
My guess is that somehow the background color is covering my views?
By the way, I do notice an error occured in the logcat:
2018-12-21 22:02:05.515 20644-20644/com.steven97102gmail.todoassistant E/RecyclerView: No adapter attached; skipping layout
However, that error occurs even if I don't set the background, and it is working just fine.
Here is my class for frament:
public class RecycleFragment extends Fragment {
private RecyclerView recyclerView;
private RecyclerView.Adapter viewAdapter;
private RecyclerView.LayoutManager viewLayouManager;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.recyler_view, container, false);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// get and configure the recycle view
recyclerView = (RecyclerView) getActivity().findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
// layout manager for recyler view
viewLayouManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(viewLayouManager);
// creates the initial cards
ArrayList<CardItem> card_lists = new ArrayList<>();
for (int i = 0;i<=10;i++){
CardItem card = new CardItem("TODO"+i,"12/" + i);
card_lists.add(card);
}
// adapter for recycler view, initialize the recycler view
viewAdapter = new RecyclerAdapter(card_lists);
recyclerView.setAdapter(viewAdapter);
// test add a new item
card_lists.add(0,new CardItem("Test Insert","12/16"));
viewAdapter.notifyItemInserted(0);
}
}
Here is my class for recycler view's adapter:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.RecyclerViewHolder> {
private ArrayList<CardItem> card_item_list;
// view holder is created from the recycler_card_item template
public static class RecyclerViewHolder extends RecyclerView.ViewHolder {
public TextView title_tv, date_tv;
public RecyclerViewHolder(LinearLayout layout) {
super(layout);
title_tv = layout.findViewById(R.id.card_item_title);
date_tv = layout.findViewById(R.id.card_item_date);
}
}
// take in a list of card items to initialize with
public RecyclerAdapter(ArrayList<CardItem> card_list) {
card_item_list = card_list;
}
#NonNull
#Override
// inflate and creates a viewholder objects, which is from the recycler care item template;
public RecyclerAdapter.RecyclerViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
// create a new card item
LinearLayout cardLayout = (LinearLayout) LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.recycler_card_item, viewGroup, false);
RecyclerViewHolder vh = new RecyclerViewHolder(cardLayout);
return vh;
}
#Override
// bind the CardItem class with the viewholder to complete the card
public void onBindViewHolder(#NonNull RecyclerViewHolder holder, int position) {
CardItem target_card = card_item_list.get(position);
holder.title_tv.setText(target_card.title);
holder.date_tv.setText(target_card.date);
}
#Override
public int getItemCount() {
return card_item_list.size();
}
}
In your code, you're trying to retrieve a recyclerview at Activity level:
recyclerView = (RecyclerView) getActivity().findViewById(R.id.recycler_view);
but the recyclerview is in your fragment. It is strange that you do not have any other errors, I would've expected the app to crash. Anyway, it should be solved in this way: change your onCreateView like this
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.recyler_view, container, false);
recyclerView = root.findViewById(R.id.recycler_view);
return root;
}
the previous line, the one that retrieved the recyclerview from the activity, is not needed anymore.

Android - Extending ViewGroup than Adding Fragment is showing up Blank

I am extending a Fragment called Scanlist. It is laid out properly and looks how I want it. Problem is I am unable to Override onInterceptTouchEvent on the extended Fragment. So I thought of extending ViewGroup, Override onInterceptTouchEvent and then add my Fragment to the ViewGroup. When I add my Fragment to the ViewGroup the Fragment is not showing up inside the ViewGroup. I know the ViewGroup is there because I am able to Log the onInterceptTouchEvent but the screen is blank.
Here is the Fragment:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mRootview = (ViewGroup) inflater.inflate(R.layout.scanlist, container, false);
mRootview.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mSharedData = new SharedData(mContext);
costomListViewArr = mSharedData.getvins();
Resources res = getResources();
mList = (ListView)mRootview.findViewById(R.id.list);
mAdapter = new Scanvinadapter(mActivity, costomListViewArr, res);
mList.setAdapter(mAdapter);
mAdapter.setimplements(this);
ViewGroup vg = new Scanlistview(mContext);
vg.addView(mRootview);
return vg;
}
Here is the ViewGroup
public class Scanlistview extends ViewGroup{
#SuppressWarnings("unused")
private final String TAG = this.getClass().getSimpleName();
LayoutInflater mInflater;
public Scanlistview(Context context) {
super(context);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
Log.v(TAG, "onInterceptTouchEvent");
return false;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
}
scanlist.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/flScanlist"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/vinlist_bg">
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/vinlist_selector"
android:listSelector="#drawable/vinlist_selector"/>
</FrameLayout>
instead of FrameLayout add your custom FrameLayout with overriden
method, also you don't actually need that FrameLayout as it has only one child, so you can just place custom ListView in the layout file

Categories