I am trying to show that when an item is clicked on an item on one fragement- details of that item is shown on the other fragment. It seems my code has no error. However , whenever I click on an item,the android app crashes and closes down.
Below is my COMPLETE(100%) code for all activities and corresponding xml files. You can simply copy these codes and run. I am not being able to find out why is it that the app crashes each time an item is clicked.
Error LogCat:
2022-04-17 19:18:09.220 8609-8609/com.example.fragment D/AndroidRuntime: Shutting down VM
2022-04-17 19:18:09.222 8609-8609/com.example.fragment E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.fragment, PID: 8609
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at com.example.fragment.MainActivity.OnItemSelected(MainActivity.java:32)
at com.example.fragment.ListFrag.onListItemClick(ListFrag.java:56)
at androidx.fragment.app.ListFragment$2.onItemClick(ListFragment.java:64)
at android.widget.AdapterView.performItemClick(AdapterView.java:330)
at android.widget.AbsListView.performItemClick(AbsListView.java:1187)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3179)
at android.widget.AbsListView$3.run(AbsListView.java:4097)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2022-04-17 19:18:09.249 8609-8609/com.example.fragment I/Process: Sending signal. PID: 8609 SIG: 9
MainActivity.java
package com.example.fragment;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements ListFrag.ItemSelected {
TextView tvDescrtiption;
ArrayList<String> descriptions;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvDescrtiption=findViewById(R.id.tvDescription);
descriptions=new ArrayList<String>();
descriptions.add("Descriptions for Item 1");
descriptions.add("Descriptions for Item 2");
descriptions.add("Descriptions for Item 3");
}
public void OnItemSelected(int index) {
tvDescrtiption.setText(descriptions.get(index));
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="horizontal"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@ id/fragmentContainerView"
android:name="com.example.fragment.ListFrag"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
tools:layout="@layout/fragment_list" />
<androidx.fragment.app.FragmentContainerView
android:id="@ id/fragmentContainerView2"
android:name="com.example.fragment.Detail"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
tools:layout="@layout/fragment_detail" />
</LinearLayout>
ListFrag.java
package com.example.fragment;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.util.ArrayList;
public class ListFrag extends ListFragment {
ItemSelected activity;
public interface ItemSelected
{
void OnItemSelected(int index);
}
public ListFrag() {
// Required empty public constructor
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
activity=(ItemSelected) context;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayList<String> data= new ArrayList<>();
data.add("1. This is Item 1");
data.add("2. This is Item 2");
data.add("3. This is Item 3");
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1,data));
}
@Override
public void onListItemClick( ListView l, View v, int position, long id) {
activity.OnItemSelected(position);
}
}
fragment_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
tools:context=".ListFrag">
<ListView
android:id="@ id/lvList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Detail.java
package com.example.fragment;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Detail extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
public Detail() {
}
public static Detail newInstance(String param1, String param2) {
Detail fragment = new Detail();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
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
return inflater.inflate(R.layout.fragment_detail, container, false);
}
}
fragment_detail.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:background="@color/yellow"
tools:context=".Detail">
<TextView
android:id="@ id/tvDescription"
android:layout_width="122dp"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="20sp" />
</FrameLayout>
CodePudding user response:
tvDescrtiption is null because it's inside a Detail fragment not directly in MainActivity, you should try and update the fragment from within.
CodePudding user response:
You are receiving a NullPointerException
because when .setText()
is invoked, it is being invoked on tvDescrtiption
, which is null. If you set a breakpoint on lines 19 (tvDescrtiption=findViewById(R.id.tvDescription);
) and 30 (tvDescrtiption.setText(descriptions.get(index));
), you will see that tvDescrtiption
is indeed null.
Why is it null? I have not used findViewById()
in the longest, but if I recall correctly, you can only retrieve a View
this way if you inflated it in the Activity
or Fragment
. tvDescrtiption
lives in fragment_detail.xml
, but in MainActivity
, you are inflating activity_main.xml
. You can currently only use findViewById()
in MainActivity
to retrieve views declared in activity_main.xml
.
CodePudding user response:
Just found the solution I was looking for
I just added the following code in my MainActivity.java
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
tvDescrtiption=findViewById(R.id.tvDescription );
}
Now, using onPostCreate ,I can refer to tvDescriptions from another Layout, it this is no more considered as null value.