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).
Related
I have a MainActivity with a BottomNavigationView with 3 items in it. When I first open the app, only one is enable, the first one.
I have a RecyclerView on the first fragment (the first item in the menu). When I click on one item of the RecyclerView, I want to switch to the second Fragment and to enable the second and third item.
I am able to switch to the second Fragment, but I can not set the items enable again.
The first Fragment with the RecyclerView is:
public class Homefragment extends Fragment implements OnItemClickListener {
private ArrayList<fileItem> mfileList = new ArrayList<>();
private RecyclerView mRecyclerView;
private fileAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private BottomNavigationView bottomNav;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
Context context = getActivity();
bottomNav = view.findViewById(R.id.bottom_navigation);
// Listing all text files
String path = Environment.getExternalStorageDirectory().toString()+"/FlexiCounts";
File directory = new File(path);
File[] filesList = directory.listFiles(new FilenameFilter() {
public boolean accept(File directory, String name) {
return name.toLowerCase().endsWith(".txt");
}
});
setRecyclerView(view, filesList);
return view;
}
private void setRecyclerView(View view, File[] files){
if (files.length > 0) {
for (int i = 0; i < files.length; i++) {
mfileList.add(new fileItem(R.drawable.ic_account_balance_black_24dp, files[i].getName().replace(".txt", ""), "25-03-2020", "07-04-2020"));
}
mRecyclerView = view.findViewById(R.id.fileRecycler);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new fileAdapter(mfileList, this);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
}
}
// the magic should happen here !
#Override
public void onItemClick(int position) {
mfileList.get(position);
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container_primary, new Dashboardfragment()).commit();
bottomNav.getMenu().getItem(1).setEnabled(true);
//bottomNav.getMenu().getItem(2).setEnabled(true);
}
}
The following lines does not work:
bottomNav.getMenu().getItem(1).setEnabled(true);
It seems to point to a null reference. I think it does not find the bottomNav define with R.id.bottom_navigation in the onCreateView method. In fact, the bottom_navigation is contained in the MainActivity layout, but that should not be a problem. I get this error:
--------- beginning of crash
2020-04-15 20:09:20.202 8673-8673/com.flexicounts.flexicounts E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.flexicounts.flexicounts, PID: 8673
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Menu android.support.design.widget.BottomNavigationView.getMenu()' on a null object reference
at com.flexicounts.flexicounts.Homefragment.onItemClick(Homefragment.java:145)
at com.flexicounts.flexicounts.fileAdapter$fileViewHolder.onClick(fileAdapter.java:50)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22429)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
create a BottomNavigationView getBottomNav() method in main activity then get it from onItemClick
in MainActivity:
public BottomNavigationView getBottomNav(){ return findViewById(R.id.bottom_navigation); }
in Homefragment:
// the magic should happen here !
#Override
public void onItemClick(int position) {
mfileList.get(position);
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container_primary, new Dashboardfragment()).commit();
((MainActivity) getActivity()).getBottomNav().getMenu().getItem(1).setEnabled(true);
//bottomNav.getMenu().getItem(2).setEnabled(true);
}
I have a problem loading my JSON data in the fragment
This method doesn't work
loadjson();
The Logcat is like this
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.asus.myapplication.fragment.kecamatan.Controller.addToRequestQueue(com.android.volley.Request)' on a null object reference
at com.example.asus.myapplication.fragment.kecamatan.KecamatanFragment.loadjson(KecamatanFragment.java:83)
at com.example.asus.myapplication.fragment.kecamatan.KecamatanFragment.onCreateView(KecamatanFragment.java:47)
I don't know why. Can anyone help?
Here's the code
public class KecamatanFragment extends Fragment {
private static final String data_url = "http://xxxxxxxxxx/daftar/get_kecamatan.php"; // kasih link prosesnya
RecyclerView mRecyclerView;
RecyclerView.Adapter mAdapter;
RecyclerView.LayoutManager mManager;
ProgressDialog pd;
ArrayList<ModelData> mItems;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_kecamatan, container, false);
pd = new ProgressDialog(getActivity());
mRecyclerView = (RecyclerView) view.findViewById(R.id.list_data);
mItems = new ArrayList<>();
mRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 3));
mAdapter = new AdapterProcess(KecamatanFragment.this, mItems);
mRecyclerView.setAdapter(mAdapter);
loadjson();
return view;
}
//proses mengambil data
private void loadjson(){
pd.setMessage("Mengambil Data");
pd.setCancelable(false);
pd.show();
Where is the rest of the loadJson method and where do you call Controller.addToRequestQueue? Your exception states that you are invoking the method addToRequestQueue on a null instance of Controller. It would appear that you need to instantiate your class Controller before calling addToRequestQueue.
This question already has answers here:
I get the error "Unreachable statement" return in android
(3 answers)
Closed 3 years ago.
I have this code, which integrates a RecyclerView within a Fragment, but this line:
mRecyclerView = (RecyclerView) mRecyclerView.findViewById(R.id.list_data);
Gives me an error, it tells me that:
Unreachable statement
And I don't know why, any idea?
Here's the code I'm using:
public class KecamatanFragment extends Fragment {
private static final String data_url = "http://xxxxxxxxxx/daftar/get_kecamatan.php"; // kasih link prosesnya
RecyclerView mRecyclerView;
RecyclerView.Adapter mAdapter;
RecyclerView.LayoutManager mManager;
ProgressDialog pd;
ArrayList<ModelData> mItems;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_kecamatan, container, false);
mRecyclerView = (RecyclerView) mRecyclerView.findViewById(R.id.list_data); <-- Unreachable statement
mItems = new ArrayList<>();
mRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 3));
mAdapter = new AdapterProcess(KecamatanFragment.this, mItems);
mRecyclerView.setAdapter(mAdapter);
loadjson();
}
enter code here
//proses mengambil data
private void loadjson(){
pd.setMessage("Mengambil Data");
pd.setCancelable(false);
pd.show();
JsonArrayRequest arrayRequest = new JsonArrayRequest(Request.Method.POST, data_url, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
pd.cancel();
Log.d("volley", "response : " + response.toString());
for (int i=0; i < response.length(); i++){
try {
JSONObject data = response.getJSONObject(i);
ModelData md = new ModelData();
md.setKecamatan(data.getString("kecamatan")); // memanggil nama array yang kita buat
mItems.add(md);
} catch (JSONException e) {
e.printStackTrace();
}
}
mAdapter.notifyDataSetChanged();
}
}, new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error) {
pd.cancel();
Log.d("volley", "error : " + error.getMessage());
}
});
Controller.getInstance().addToRequestQueue(arrayRequest);
}
}
Unreachable statement
That's expected error, because you're stopping the onCreateView method after you're giving it a return statement:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// You've already close the method when you're giving a return
return inflater.inflate(R.layout.fragment_kecamatan, container, false);
// so this won't be reachable, hence the unreachable error raised.
mRecyclerView = (RecyclerView) mRecyclerView.findViewById(R.id.list_data);
...
}
So, you either need to inflate the Layout first and bind the view then return the inflated view or move the view binding after the return statement to another method.
As mentioned by ישו אוהב אותך, You're returning the inflated view immediately. keep a reference to the inflated view and return it at the end. Also, you probably want to use findViewById on the inflated view and not on mRecyclerView.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_kecamatan, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.list_data);
mItems = new ArrayList<>();
mRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 3));
mAdapter = new AdapterProcess(KecamatanFragment.this, mItems);
mRecyclerView.setAdapter(mAdapter);
loadjson();
return view;
}
I try to create a HORIZONTAL recyclerView but recyclerView can't find the context here is my Fragmnet code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.context =context;
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
ArrayList<CategoryModel> categoryModels = null;
RecyclerView recyclerView = container.findViewById(R.id.category_recycler);
// recyclerView.setHasFixedSize(true);
CategoryAdapter adapter = new CategoryAdapter(context,CategoryData.getCategory());
recyclerView.setAdapter(adapter);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
return inflater.inflate(R.layout.main_fragment, container, false);
}
and here is Recycler view adapter code:
public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHolder> {
Context context;
ArrayList<CategoryModel> categorys;
public CategoryAdapter(Context context, ArrayList<CategoryModel> categoryModels) {
this.categorys = categoryModels;
this.context = context;
}
#NonNull
#Override
public CategoryAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.product_category,parent,false);
return new ViewHolder(view);
}
i'm also attached the Debug result please check the image
Try like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
// Defines the xml file for the fragment
return inflater.inflate(R.layout.main_fragment, parent, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// Inflate the layout for this fragment
ArrayList<CategoryModel> categoryModels = null;
RecyclerView recyclerView = view.findViewById(R.id.category_recycler);
// recyclerView.setHasFixedSize(true);
CategoryAdapter adapter = new CategoryAdapter(getContext(), CategoryData.getCategory());
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
To use Context inside Fragment use getContext() method .
CategoryAdapter adapter = new CategoryAdapter(getContext(),CategoryData.getCategory());
From official doc
Return the Context this fragment is currently associated with.
If you are using Context only for inflating view inside onCreateViewHolder method in CategoryAdapter class then you don't need to pass Context in Constructor. You can get Context from ViewGroup which is first parameter of the onCreateViewHolder method.
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.product_category,parent,false);
In your onCreate() fragment callback I see this line:
public void onCreate(Bundle savedInstanceState) {
...
this.context =context;
...
}
This line doesn't do anything; there's no context argument to the onCreate() method or anything like that, so you're just assigning a variable back to itself. Since your Context context field doesn't have an explicit intialization, the default is null. So this is the same as writing
public void onCreate(Bundle savedInstanceState) {
...
this.context = null;
...
}
Later on, in onCreateView(), you're instantiating your adapter with this line:
CategoryAdapter adapter = new CategoryAdapter(context,CategoryData.getCategory());
Because of what I said above, this is functionally the same as
CategoryAdapter adapter = new CategoryAdapter(null, CategoryData.getCategory());
To solve this, you need some place to get a Context instance from. Fragments are often "attached" to a context, and, when they're attached, you can get that context by calling getContext(). A fragment is guaranteed to be attached to a context in the onActivityCreated() callback, so you will want to move your adapter creation to that callback instead of onViewCreated().
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.main_fragment, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
CategoryAdapter adapter = new CategoryAdapter(getContext(), CategoryData.getCategory());
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
RecyclerView recyclerView = getView().findViewById(R.id.category_recycler);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(layoutManager);
}
I have a function in a fragment (Frag_Lista) that changes its cardView dynamically using the output of a query.
The first time i call it from that fragment and it works. The second time i would call it from the main activity, but i can't set correctly the second parameter, the view.
Frag_Lista
public void function_in_fragment() {
//some code
Context context = getActivity();
DBhelper database = ((MainActivity)getActivity()).getDatabase();
Cursor cursor=database.ottieni_tutto();
genera_lista(cursor,getView());
}
public void genera_lista(Cursor cursor, View v) {
list.clear();
if(cursor!=null) {
if(cursor.moveToFirst()) {
while (!cursor.isAfterLast()) {
//Log.d(TAG,cursor.getString(cursor.getColumnIndex(DBhelper.COL_NOME)));
String nome = cursor.getString(cursor.getColumnIndex(DBhelper.COL_NOME));
String tipo = cursor.getString(cursor.getColumnIndex(DBhelper.COL_TIPO));
String difficolta = cursor.getString(cursor.getColumnIndex(DBhelper.COL_DIFFICOLTA));
String immagine = cursor.getString(cursor.getColumnIndex(DBhelper.COL_IMMAGINE));
Food_Card food_card = new Food_Card(immagine, nome, tipo, difficolta);
list.add(food_card);
cursor.moveToNext();
}
cursor.close();
}
else Log.d(TAG,"Cursor vuoto");
}
else Log.d(TAG,"Cursor nullo");
recyclerView = (RecyclerView) v.findViewById(R.id.recyclerView);
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
adapter=new food_adapter(getActivity(),list);
recyclerView.setAdapter(adapter);
}
MainActivity
public void function_in_mainActivity(String[] parametri) {
Cursor cursor=database.query_filtri(parametri);
Frag_Lista nothing=new Frag_Lista();
View v= ?
nothing.genera_lista(cursor,v);
}
How can i pass correctly the current view?
Frag_Lista
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.frag_lista, container, false);
setHasOptionsMenu(true);
return(v);
}
Change your onCreateView like this
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.frag_lista, container, false);
recyclerView = (RecyclerView) v.findViewById(R.id.recyclerView);
setHasOptionsMenu(true);
return(v);
}
Crate a field inside your Fragment for recyclerView.
Now you always have a reference to the RecyclerView and don't need to pass it as a argument to the method.
public void genera_lista(Cursor cursor)