I have a main Activity.class that runs a Fragment (not FragmentActivity) via ViewPager. And I have a custom adapter with recyclerview list inside the fragment. There is an issue with accessing adapter outside and inside the Fragment. So:
This code fully works:
private List<MyQuestionList> theList;
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
recyclerView = (RecyclerView) theview.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
theList = new ArrayList<>();
requestQueue = Volley.newRequestQueue(getContext());
adapter = new MyQuestionsAdapter(theList, getContext());
recyclerView.setAdapter(adapter);
updateAdapter(); // <-- ATTENTION PLEASE, I'VE CALLED THE FUNCTION INSIDE THE FRAGMENT
}
public void updateAdapter(){ // <-- METHOD IS PUBLIC
removeItem(0);
}
***** And there is located parser's method where items are fetching from server
and adding to recyclerview via adapter successfully.
But the code is too long, and anyway there is nothing interesting :) *****
private void removeItem(int item){
theList.remove(item);
adapter.notifyDataSetChanged();
}
But when I call the same method (updateAdapter) from main Activity.class like this (not inside the fragment on run):
Fragment_Questions frau = new Fragment_Questions();
frau.updateAdapter();
code doesn't work. Here is log:
Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.List.remove(int)' on a null object reference
Since you said that a Fragment_Questions is already added to a ViewPager, use the reference of the added Fragment_Questions object to call updateAdapter().
In the code given below, you are just creating an object but never adding it to a viewpager. Hence, the onCreateView method is never being called, which leads to the NullPointerException.
Related
I'm very new to android development as I just took a class of it only now, so I'm very confused with my current situation as I am writing the codes using the references I currently have at the moment.
I have also been trying to use references from other sources, though, sadly, I can't really comprehend how those really works.
My current assignment is that I have to make an application that serves as a catalog for movies and tv shows using fragments, and the following is the codes of one of the fragments:
public class MovieFragment extends Fragment {
View view;
private String[] titleMovie;
private String[] descMovie;
private TypedArray posterMovie;
private String[] genreMovie;
private String[] castMovie;
private String[] duration;
private String[] directorMovie;
private MovieAdapter adapter;
private ArrayList<Movie> movies;
private RecyclerView recyclerView;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.mv_fragment,container,false);
recyclerView = view.findViewById(R.id.mv_list);
adapter = new MovieAdapter(getContext(), movies);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()) {});
recyclerView.setAdapter(adapter);
return view;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prepare();
addItem();
}
private void prepare() {
titleMovie = getResources().getStringArray(R.array.name_mv);
descMovie = getResources().getStringArray(R.array.desc_mv);
posterMovie = getResources().obtainTypedArray(R.array.poster_mv);
genreMovie = getResources().getStringArray(R.array.genre_mv);
castMovie = getResources().getStringArray(R.array.cast_mv);
directorMovie = getResources().getStringArray(R.array.director_mv);
duration = getResources().getStringArray(R.array.duration);
}
private void addItem() {
movies = new ArrayList<>();
for (int i = 0; i < titleMovie.length; i++){
Movie movie = new Movie();
movie.setTitleMovie(titleMovie[i]);
movie.setDescMovie(descMovie[i]);
movie.setPosterMovie(posterMovie.getResourceId(i,-1));
movie.setGenreMovie(genreMovie[i]);
movie.setDuration(duration[i]);
movie.setDirectorMovie(directorMovie[i]);
movie.setCastMovie(castMovie[i]);
movies.add(movie);
}
adapter.setMovie(movies);
}
}
And when I try to run the application from the emulator provided in Android Studio, I got the following error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.wisnu_1605450.utsmobpro, PID: 18250
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.wisnu_1605450.utsmobpro.MovieAdapter.setMovie(java.util.ArrayList)' on a null object reference
at com.wisnu_1605450.utsmobpro.MovieFragment.addItem(MovieFragment.java:74)
at com.wisnu_1605450.utsmobpro.MovieFragment.onCreate(MovieFragment.java:47)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2586)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:838)
at androidx.fragment.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1197)
at androidx.fragment.app.FragmentTransition.calculateFragments(FragmentTransition.java:1080)
at androidx.fragment.app.FragmentTransition.startTransitions(FragmentTransition.java:119)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1866)
Any explanation on why I screwed up is very much appreciated, will also give more of the codes if necessary for the context.
From the Fragment Life cycle documentation, onCreate event will be called before onCreateView event. That mean when you call adapter.setMovie(movies), the adapter is not created. It'll cause a NullPointerException.
You should call addItem in onViewCreated or onStart event.
OnCreate() method should be called before onCreateView() and after that onViewCreated() will be called.
Whereas in your code prepare(),addItem() methods are called in onCreate() so that instance not create for your MovieAdapter().please remove prepare(),addItem() methods in onCreate() and place it OnViewCreated()
I'm trying to follow this tutorial
I have a project that uses the Sidebar Navigation, so I have one MainActivity and multiple Fragments. At ~6:20 into the video, you can see the following code:
PersonListAdapter adapter = new PersonListAdapter(
this,
R.layout.adapter_view_layout,
peopleList);
The constructor for the PersonListAdapter Class is:
public PersonListAdapter(Context context, int resource, ArrayList<Attacks> objects) {
super(context, resource, objects);
this.mContext = mContext;
mResource = resource;
}
The problem lies with Context.
If I use the word "this", there is a red line.
If I replace
"this" with "getActivity()", there is no red line, but the app
crashes when I run it.
I've also tried "this.getContext()" and "this.getActivity()"
I have also tried replacing "this" with "getActivity().getApplicationContext()", and the app crashes.
The tutorial uses MainActivity.java, but my code is in FragmentCharacters.java. I don't know what I'm supposed to write in place of "this", or if I need to change something in the PersonListAdapter class for Context.
You cannot use a Fragment as a Context, because Fragment doesn't inherit from Context.
However, if you consult the Fragment lifecycle, you can see that the Fragment has access to its host Activity at any time between the lifecycle callbacks OnActivityCreated() and onDestroyView(). If you try to access the Activity before OnActivityCreated(), for example, it will probably return null.
So make sure you are calling getActivity() from within onActivityCreated() or later, which will make sure your Activity is available.
UPDATE, I Provided a Case Example inside the Code Snippets as well, and I chose "FragmentName" as Fragment name for example.
First Look at This Fragment Structure.
I Added [mAdapter] in Both onCreate and onCreateView
And I Added FragmentName.this for the Forth argument
The Reason is, You can send data from The Adapter to Other Activities with it, for Example FragmentName.mAdapter.getLayoutPosition()
But, Let's assume We have an ImageView which is In MainActivity and we want to use it in our Adapter, So let's Establish an ImageView In our Fragment as well, Notice I Declared the ImageView Inside onCreate
And, For Another Example, Let's Assume we Have a Public Void at the End of our Fragment as Well, It can be Literally Anything. I Named it ExampleClass
/////////FIRST TAKE A LOOK AT FRAGMENT//////////
public class FragmentName extends Fragment {
PersonListAdapter adapter;
ImageView imageView; // For Example thi ImageView is from MainActivity
public FragmentName() {
...
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
adapter = new PersonListAdapter(getContext(), R.layout.adapter_view_layout, peopleList, FragmentName.this);
imageView = (ImageView) getActivity().findViewById(R.id.ImageView);
// This Imageview is in Another Activity, Like MainActivity
// So we Need to Find it Using 'getActivity()'
...
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
adapter = new PersonListAdapter(getContext(), R.layout.adapter_view_layout, peopleList, FragmentName.this);
}
}
public void ExampleClass(int color, ...) {
...
}
////////////////////////////////////////////////////////////////
Now, Let's take this Example into our Adapter as well, to Show how it can be Used.
But, In the Adapter Use [FragmentName], Instead of [Fragment] like Below:
///////////NOW INSIDE YOUR ADAPTER/////////////
public class PersonListAdapter extends RecyclerView.Adapter < PersonListAdapter.myViewHolder > {
FragmentName myFragment; // SEE WHAT HAPPENDED HERE?
...
public PersonListAdapter(Context context, int resource, ArrayList < Attacks > objects, FragmentName fragment) {
super(context, resource, objects);
this.mContext = mContext;
mResource = resource;
this.myFragment = fragment
}
#Override
public PersonListAdapter.myViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Example use of myFragment
// Lets Execute ExmpleClass inside the Fragment
myFragment.ExampleClass(int color, ...);
// Let's Use the ImageView from MainActivity Here
myFragment.imageView.setImageRresource(...);
...
}
...
// YOU CAN NOW USE "myFragment" As a Context In your Adapter
The Good Part about this is That You can Use Fragment As CONTEXT in Your PersonListAdapter
Update: The second Code, onCreateViewHolder is wrong, it has to be inside a ClickListener in ViewHolder or onBindViewHolder
Ok so i tried to learn of all These other questions here, but i am not getting the hang of it, so i decided to ask by myself.
I got a Main Activity with different Fragments for changing the views (used the Android Standard sidebar activity template). From there the user creates Tasks via a separate Acitivty which Returns the values. In the Main Activity the Tasks are getting stored into the SQLite-database. So far it works.
Now i have the Fragment TaskList with the corresponding layout TaskList_main.xml. In this XML file i got a simple ListView which i want to fill with the values from the database. My Problem is where to write that method and when to Access it. the method would be
public void showAllListEntries() {
List<TaskData> TaskList = datasource.getAllTasks();
//Daten werden im ArrayAdapter gespeichert
ArrayAdapter<TaskData> TaskListArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, TaskList);
ListView TaskDataListView = (ListView) findViewById(R.id.TaskListView);
TaskDataListView.setAdapter(TaskListArrayAdapter);
}
My Fragment is empty like this atm
public class TaskList extends Fragment {
View view;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.activity_main_tasklist, container, false);
return view;
}
}
I can also send the main Activity if you like but it's a bit messy
So can someone tell me how i get this to work? And did i explain my Problem clearly?
You can do it in onCreateView. But you should make an async call to get the tasks to display and have your fragment as a listener. When you get the tasks you can create your adapter and attach it to the ListView.
And you should have a ProgressBar in TaskList_main.xml (which should be renamed to task_list_fragment.xml, I don't think there is a naming convention for layouts, but this is quite used) and hide it when you receive the data.
I've got the following function:
public static class ListFragment extends Fragment {
private ParseQueryAdapter<ParseObject> mainAdapter;
private ListView listView;
public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState )
{
View rootView = inflater.inflate(R.layout.fragment_list, container, false );
mainAdapter = new ParseQueryAdapter<ParseObject>( this, "Todo" );
mainAdapter.setTextKey("title");
mainAdapter.setImageKey("image");
// Initialize ListView and set initial view to mainAdapter
listView = (ListView) findViewById(R.id.list);
listView.setAdapter(mainAdapter);
mainAdapter.loadObjects();
return rootView;
}
}
The errors returned are:
The constructor ParseQueryAdapter(MainActivity.ListFragment, String) is undefined MainActivity.java
Cannot make a static reference to the non-static method findViewById(int) from the type Activity MainActivity.java
I can assume that the first one due to the change of the object of type this but I would like a more seasoned input on the correct fix.
The second error though thoroughly confounds as it appears to be valid to my eyes.
Appreciate any input.
1) Change the instantiation of ParseQueryAdapter as follows. The code is in a Fragment, but ParseQueryAdapter requires a Context object.
mainAdapter = new ParseQueryAdapter<ParseObject>( this.getActivity(), "Todo" );
2) Remove the static modifier from your class definition.
I have a dialog which extends DialogFragment:
public class MyCustomDialogFragment extends DialogFragment {
static MyCustomDialogFragment newInstance() {
return new MyCustomDialogFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.institutional_info_custom_list, container, false);
return view;
}
}
And this is where I use this dialog (it is inside an onclick listener):
MyCustomDialogFragment newFragment = MyCustomDialogFragment.newInstance();
View DialogView = newFragment.getView();
DetailListView = (ListView) DialogView.findViewById(R.id.custom_dialog_list);
final MasterDetailArrayAdapter adapter = new MasterDetailArrayAdapter(ComeHaInvestito.this, MasterAndDetailstatisticsInfoList);
DetailListView.setAdapter(adapter);
newFragment.show(getFragmentManager(), "master_detail_dialog");
MasterAndDetailstatitiscsInfoList is a list I am using with my custom ArrayAdapter, but the problem is with the View of the DialogFragment: it is null! Why? I read the android documentation and they say that getView() returns the View of the dialog which is the one returned by the onCreateView() overriden method.
So why I get a null pointer exception when trying to revocer the ListView which is in the dialogFragments layout???
Sorry but this does not make sense to me. An explanation will be appreciated.
Thanks!
Use setArguments() to provide the dataset for the Adapter to the DialogFragmet. In DialogFragment override onViewCreated(), retrieve the ListView, create the Adapter and set it to the ListView