Fragment.getView on a null object reference
При определении фрагмента из активити возникает ошибка:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.app.Fragment.getView()' on a null object reference
Код активити:
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private Bundle b;
private Toolbar toolbar;
private List<String> sp_pickpas_list;
private Spinner sp_pas;
private View root;
private ImageButton ib_addpas;
private RecyclerView rv_fams;
private LinearLayoutManager llm;
private AppDatabase db;
private FamDao fdao;
private ApiaryDao apdao;
private String pas_name;
private Apiary newap;
private List<Apiary> all;
private boolean is_pas_picked = false;
private List<Fam> fams;
private Intent i_addfam;
private TextView error;
private RVA_fam rva_fam;
private int id_pas;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
b = getIntent().getExtras();
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
BottomNavigationView navView = findViewById(R.id.nav_view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(binding.navView, navController);
if(b!=null && (int)b.get("Statement")==1) Toast.makeText(this, "Семья успешно добавлена", Toast.LENGTH_LONG).show();
root = getFragmentManager().findFragmentById(R.layout.fragment_home).getView(); //ошибка ссылается на эу строку
sp_pas = findViewById(R.id.sp_paspick);
sp_pickpas_list = new ArrayList<String>();
sp_pickpas_list.add("=Выберите пасеку=");
rv_fams = root.findViewById(R.id.rv_fams);
error = root.findViewById(R.id.tv_error);
newap = new Apiary();
rv_fams.setVisibility(View.INVISIBLE);
error.setVisibility(View.VISIBLE);
i_addfam = new Intent(this, AddFamily.class);
llm = new LinearLayoutManager(this);
llm.setOrientation(RecyclerView.VERTICAL);
rv_fams.setLayoutManager(llm);
db = app.getInstance().getDatabase();
fdao = db.FamDao();
apdao = db.ApiaryDao();
rva_fam = new RVA_fam();
rv_fams.setAdapter(rva_fam);
getListPas();
ArrayAdapter<String> sp_pas_adap = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, sp_pickpas_list);
sp_pas.setAdapter(sp_pas_adap);
sp_pas.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
if(i!=0) {
fams = fdao.getFams(i);
if(fams.size()!=0) {
Log.i("H_frag", "fams size isnt null");
rv_fams.setVisibility(View.VISIBLE);
rva_fam.setItems(fams);
error.setVisibility(View.INVISIBLE);
} else {
Log.i("H_frag", "fams size is null");
rva_fam.clearItems();
rv_fams.setVisibility(View.INVISIBLE);
error.setVisibility(View.VISIBLE);
}
id_pas=i;
is_pas_picked = true;
} else {
Log.i("H_frag", "picked null spinner element");
rva_fam.clearItems();
rv_fams.setVisibility(View.INVISIBLE);
error.setVisibility(View.VISIBLE);
is_pas_picked = false;
}
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
ib_addpas.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (is_pas_picked){
i_addfam.putExtra("pas_id", id_pas);
startActivity(i_addfam);
} else {
CreateDialog(savedInstanceState).show();
}
}
});
}
public Dialog CreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Добавить пасеку");
LayoutInflater li = LayoutInflater.from(this);
View v = li.inflate(R.layout.ad_add_pas, null);
builder.setView(v);
EditText etName = v.findViewById(R.id.et_pasname);
builder.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
pas_name = etName.getText().toString();
if (pas_name.compareTo("") == 0) {
Toast.makeText(MainActivity.this,
"Поле не заполнено", Toast.LENGTH_SHORT).show();
} else {
newap.kol_fams = 0;
newap.name = pas_name;
apdao.insert_apiary(newap);
dialog.cancel();
}
}
});
builder.setNegativeButton("ОТМЕНА", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
}
});
return builder.create();
}
private void getListPas(){
all = apdao.getAllfromApiary();
for(int i=0; i<all.size(); i++){
sp_pickpas_list.add(all.get(i).name + " (" + all.get(i).kol_fams + ")");
}
}
}
Подозреваю, что проблема может быть в том, что переключение между фрагментами реализовано через BottomNavigationView, поэтому прилагаю разметку активити и фрагмента. Кстати, фрагмент без проблем можно было открыть через нажатие кнопки в BottomNavigationView.
Разметка активити:
<?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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
style="@style/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="MissingConstraints">
<Spinner
android:id="@+id/sp_paspick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="1dp"
android:layout_marginTop="21dp"
android:textSize="24sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.appcompat.widget.Toolbar>
<fragment
android:id="@+id/nav_host_fragment_activity_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="60dp"
app:defaultNavHost="true"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar"
app:navGraph="@navigation/mobile_navigation" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
Разметка фрагмента:
<?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_fams"
android:layout_width="383dp"
android:layout_height="653dp"
android:layout_marginStart="8sp"
android:layout_marginEnd="8sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.428"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/ib_add"
android:layout_width="63sp"
android:layout_height="60sp"
android:layout_marginEnd="64dp"
android:layout_marginBottom="64dp"
android:background="@null"
android:scaleType="fitXY"
android:src="@android:drawable/ic_input_add"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/tv_error"
android:layout_width="252dp"
android:layout_height="158dp"
android:layout_marginBottom="284dp"
android:text="В выбранной пасеке отсутствуют семьи"
android:textSize="30sp"
android:textAlignment="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.496"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Честно говоря, не знаю как проблему решить, более того, не знаю даже как к ней подступиться. Подскажите, пожалуйста, в чем она может быть. Спасибо!
Ответы (1 шт):
Вы пишите код исходя из предположения о синхронной работе фрагментов и транзакций по добавлению оных на экран. Оно работает не так, оно работает асинхронно.
Судя по коду вы, кажется, пытаетесь из спиннера в активити управлять разметкой фрагмента. Тут можно по разному сделать:
- Тулбар со спиннером перенести во фрагмент. Тогда и проблема сама собой исчезнет - весь код будет внутри фрагмента.
- Обращаться к разметке фрагмента только тогда, когда это нужно (в onItemSelected), а не сразу в onCreate актвити. Это сделает код чуть проще, но всё равно это будет своего рода костыль.