我有一个应用程序,只需按
button
保存值,这个button
打开一个dialog
,这里的问题是只有我可以按一次,因为之后它会抛出java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
然后明显崩溃了。
我还有一个 recyclerview
,其中所有值在用 button
添加后都可以看到。
堆栈跟踪:
致命异常:主要 进程:com.example.calularpr,PID:17510 java.lang.IllegalStateException:指定的子级已经有一个 父母。您必须首先对子级的父级调用removeView()。 在 android.view.ViewGroup.addViewInner(ViewGroup.java:5235) 在 android.view.ViewGroup.addView(ViewGroup.java:5064) 在 android.view.ViewGroup.addView(ViewGroup.java:5036) 在 androidx.appcompat.app.AlertController.setupCustomContent(AlertController.java:657) 在 androidx.appcompat.app.AlertController.setupView(AlertController.java:475) 在 androidx.appcompat.app.AlertController.installContent(AlertController.java:233) 在 androidx.appcompat.app.AlertDialog.onCreate(AlertDialog.java:279) 在 android.app.Dialog.dispatchOnCreate(Dialog.java:419) 在 android.app.Dialog.show(Dialog.java:313) 在 androidx.appcompat.app.AlertDialog$Builder.show(AlertDialog.java:1009) 在 com.example.calcularpr.MainActivity$2.onClick(MainActivity.java:111) 在 android.view.View.performClick(View.java:7448) 在 com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1131) 在 android.view.View.performClickInternal(View.java:7425) 在 android.view.View.access$3600(View.java:810) 在 android.view.View$PerformClick.run(View.java:28305) 在 android.os.Handler.handleCallback(Handler.java:938) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:223) 在 android.app.ActivityThread.main(ActivityThread.java:7656) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Java 代码:
package com.example.calcularpr;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
FirebaseDatabase db;
EditText prMark;
ConstraintLayout layout;
RecyclerView recyclerView;
DatabaseReference dbReference;
ArrayList<Marks> data;
LayoutInflater inflater;
View addView;
Button addNewPrMain;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = FirebaseDatabase.getInstance();
layout = findViewById(R.id.layout);
inflater = getLayoutInflater();
addView = inflater.inflate(R.layout.dialog_add,null);
prMark = addView.findViewById(R.id.PbancaPR);
dbReference = db.getReference("Pesos");
addNewPrMain = findViewById(R.id.buttonAdd);
//RECYCLERVIEW
data = new ArrayList<>();
recyclerView = findViewById(R.id.recyclerview);
recyclerViewAdapter adapter = new recyclerViewAdapter(this,data);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
dbReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot: snapshot.getChildren()) {
Marks marks = dataSnapshot.getValue(Marks.class);
data.add(marks);
}
adapter.notifyDataSetChanged();
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
//RECYCLERVIEW
//ADD PR BUTTON
addNewPrMain.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MainActivity.this);
dialogBuilder.setTitle("Añadir peso")
.setMessage("Añadir peso?")
.setPositiveButton("Si", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String prMarkData = prMark.getText().toString();
setData(prMarkData);
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
}).setView(addView)
.show();
/* if (v.getParent() != null) {
((ViewGroup) v.getParent()).removeView(v); //Tried this, but i think idk how to apply it correctly
}
layout.addView(v); */
}
});
//ADD PR
}
public void setData (String peso) {
Marks mark = new Marks(peso);
dbReference.push().setValue(mark);
Toast.makeText(MainActivity.this,"Marca añadida",Toast.LENGTH_SHORT).show();
}
}
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:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PR Banca "
android:textSize="34sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.1" />
<Button
android:id="@+id/buttonAdd"
android:layout_width="73dp"
android:layout_height="71dp"
android:text="+"
android:textSize="34sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.952"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.975" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="409dp"
android:layout_height="528dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.561" />
</androidx.constraintlayout.widget.ConstraintLayout>
Recyclerview 适配器:
package com.example.calcularpr;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class recyclerViewAdapter extends RecyclerView.Adapter<recyclerViewAdapter.ViewHolder> {
Context context;
ArrayList<Marks> data;
public recyclerViewAdapter (Context context, ArrayList<Marks> data) {
this.context = context;
this.data = data;
}
@NonNull
@Override
public recyclerViewAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.pr_card,parent,false);
if (view.getParent() != null) {
parent.removeView(view);
}
return new recyclerViewAdapter.ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull recyclerViewAdapter.ViewHolder holder, int position) {
Marks marks = data.get(position);
holder.name.setText(marks.getWeight());
}
@Override
public int getItemCount() {
return data.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView name;
public ViewHolder(@NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.name);
}
}
}
Recyclerview 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:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content ">
<LinearLayout
android:id="@+id/add_category_layout"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginEnd="6dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="60"
android:textSize="48sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="90dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</LinearLayout>
我尝试了不同的事情,比如检查
View view = inflater.inflate(R.layout.pr_card,parent,false);
确保附加到root是假的,你也可以在java代码中看到我试图删除视图,但它不起作用,也许是因为我不知道到底如何来实施它。
问题可能是因为您之前已经膨胀了 addView 布局并将其分配给 prMark EditText。尝试一下这是否可以解决问题。在单击侦听器中,创建 addView 布局的新实例,然后将其设置为对话框的视图,如下所示:
addNewPrMain.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Create new instance of addView
View addView = inflater.inflate(R.layout.dialog_add, null);
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MainActivity.this);
dialogBuilder.setTitle("Añadir peso")
.setMessage("Añadir peso?")
.setPositiveButton("Si", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String prMarkData = prMark.getText().toString();
setData(prMarkData);
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
}).setView(addView)
.show();
}
});