java.lang.RuntimeException:Parcelable在写入可序列化对象时遇到IOException(名称=[[Landroid.widget.Button;)
我正在编写一个数独解算器应用程序。但由于未知原因,它一直崩溃 当我试着调试应用程序时,我没有得到一行特定的代码来告诉我是什么导致它崩溃。但是,我看到它在整个solverActivity类中没有崩溃,并在大约半秒钟内显示正确的suoku板,然后崩溃 我将错误消息解释为我试图发送一个不可序列化的对象(按钮)。但是,我在代码中找不到我尝试这样做的地方 我在谷歌上搜索过,但没有找到任何对我有帮助的解决方案。这促使我写了这篇文章 这是stacktrace 2020-03-08 09:40:19.559 15499-15499/com.example.sodukosolver E/AndroidRuntime:致命异常:main 进程:com.example.sodukosolver,PID:15499 java.lang.RuntimeException:Parcelable在写入可序列化对象时遇到IOException(名称=[[Landroid.widget.Button;) 位于android.os.Parcel.WriteSeriable(Parcel.java:1833) 位于android.os.Parcel.writeValue(Parcel.java:1780) 位于android.os.Parcel.writeArrayMapInternal(Parcel.java:928) 位于android.os.BaseBundle.WriteToParceliner(BaseBundle.java:1584) 位于android.os.Bundle.writeToParcel(Bundle.java:1253) 在android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4505) 在android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145) 位于android.os.Handler.handleCallback(Handler.java:883) 位于android.os.Handler.dispatchMessage(Handler.java:100) 位于android.os.Looper.loop(Looper.java:214) 位于android.app.ActivityThread.main(ActivityThread.java:7356) 位于java.lang.reflect.Method.invoke(本机方法) 位于com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 原因:java.io.NotSerializableException:androidx.appcompat.widget.AppCompatButton 位于java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1240) 位于java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1434) 位于java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1230) 位于java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1434) 位于java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1230) 位于java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354) 位于android.os.Parcel.WriteSeriable(Parcel.java:1828) 位于android.os.Parcel.writeValue(Parcel.java:1780) 位于android.os.Parcel.writeArrayMapInternal(Parcel.java:928) 位于android.os.BaseBundle.WriteToParceliner(BaseBundle.java:1584) 位于android.os.Bundle.writeToParcel(Bundle.java:1253) 在android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4505) 在android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145) 位于android.os.Handler.handleCallback(Handler.java:883) 位于android.os.Handler.dispatchMessage(Handler.java:100) 位于android.os.Looper.loop(Looper.java:214) 位于android.app.ActivityThread.main(ActivityThread.java:7356) 位于java.lang.reflect.Method.invoke(本机方法) 位于com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 这是我的主要活动,我认为它可以正常工作(很抱歉没有遵循干净的代码:/)java.lang.RuntimeException:Parcelable在写入可序列化对象时遇到IOException(名称=[[Landroid.widget.Button;),java,android-studio,Java,Android Studio,我正在编写一个数独解算器应用程序。但由于未知原因,它一直崩溃 当我试着调试应用程序时,我没有得到一行特定的代码来告诉我是什么导致它崩溃。但是,我看到它在整个solverActivity类中没有崩溃,并在大约半秒钟内显示正确的suoku板,然后崩溃 我将错误消息解释为我试图发送一个不可序列化的对象(按钮)。但是,我在代码中找不到我尝试这样做的地方 我在谷歌上搜索过,但没有找到任何对我有帮助的解决方案。这促使我写了这篇文章 这是stacktrace 2020-03-08 09:40:19.559 1
导入android.view.view;
导入android.widget.AdapterView;
导入android.widget.ArrayAdapter;
导入android.widget.Button;
导入android.widget.Spinner;
导入java.util.HashMap;
公共类MainActivity扩展AppCompativeActivity实现AdapterView.OnItemSelectedListener{
私有按钮[][]垂直按钮=新按钮[9][9];
私人按钮[][]景观按钮=新按钮[9][9];
私有按钮、清除按钮;
私有HashMap solveMap=新HashMap();
私人纺纱机;
私有字符串编号;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
微调器=findViewById(R.id.number\u微调器);
ArrayAdapter=ArrayAdapter.createFromResource(这个,R.array.numbers,android.R.layout.simple\u微调器\u项);
setDropDownViewResource(android.R.layout.simple\u微调器\u下拉菜单\u项);
旋转器。设置适配器(适配器);
spinner.setOnItemSelectedListener(此);
solveButton=findViewById(R.id.solve_按钮);
clearButton=findViewById(R.id.clear\u按钮);
setOnClickListener(v->loadResult());
if(savedInstanceState!=null&&getResources().getConfiguration().orientation==Configuration.orientation\u纵向){
solveMap=(HashMap)savedInstanceState.getSerializable(“solveMap”);
垂直按钮=查找按钮(垂直按钮,“按钮”,false);
setOnClickListener(v->clearAllButtons(垂直按钮));
加载按钮值(垂直按钮);
}
else if(savedInstanceState!=null&&getResources().getConfiguration().orientation==Configuration.orientation\u){
solveMap=(HashMap)savedInstanceState.getSerializable(“solveMap”);
landscapeButtons=findButtons(landscapeButtons,“按钮”,false);
setOnClickListener(v->clearAllButtons(landscapeButtons));
加载按钮值(景观按钮);
}
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import java.util.HashMap;
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
private Button[][] verticalButtons = new Button[9][9];
private Button[][] landscapeButtons = new Button[9][9];
private Button solveButton, clearButton;
private HashMap<String, Integer> solveMap = new HashMap<>();
private Spinner spinner;
private String number;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spinner = findViewById(R.id.number_spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.numbers, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(this);
solveButton = findViewById(R.id.solve_button);
clearButton = findViewById(R.id.clear_button);
solveButton.setOnClickListener(v -> loadResult());
if(savedInstanceState != null && getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
solveMap = (HashMap<String, Integer>) savedInstanceState.getSerializable("solveMap");
verticalButtons = findButtons(verticalButtons,"button", false);
clearButton.setOnClickListener(v -> clearAllButtons(verticalButtons));
loadButtonValue(verticalButtons);
}
else if(savedInstanceState != null && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
solveMap = (HashMap<String, Integer>) savedInstanceState.getSerializable("solveMap");
landscapeButtons = findButtons(landscapeButtons,"buttons", false);
clearButton.setOnClickListener(v -> clearAllButtons(landscapeButtons));
loadButtonValue(landscapeButtons);
}
else if(savedInstanceState == null && getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
verticalButtons = findButtons(verticalButtons,"button", true);
clearButton.setOnClickListener(v -> clearAllButtons(verticalButtons));
}else{
landscapeButtons = findButtons(landscapeButtons,"buttons", true);
clearButton.setOnClickListener(v -> clearAllButtons(landscapeButtons));
}
}
/**
* This method finds the buttons of the board based after the orientation of the device
* @param sudokuButtons 2D Array of Buttons[9][9]
* @param orientation String referring to xml id, button = PORTRAIT(xml), buttons = LANDSCAPE(xml)
* @param boardIsEmpty boolean used to determine if code is being created for the first time or being recreated
* @return a 2D Array of buttons[9][9]
*/
private Button[][] findButtons(Button[][] sudokuButtons, String orientation, boolean boardIsEmpty){
for(int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++){
String buttonID = orientation + i + j;
int resId = getResources().getIdentifier(buttonID, "id", getPackageName());
sudokuButtons[i][j] = findViewById(resId);
sudokuButtons[i][j].setOnClickListener(v -> updateButtonValue(v));
if(boardIsEmpty) {
solveMap.put("key" + i + j , 0);
}
}
return sudokuButtons;
}
/**
* This method updates the values in a button after it has been clicked
* @param view
*/
private void updateButtonValue(View view){
Button button = findViewById(view.getId());
String buttonName = getResources().getResourceEntryName(view.getId());
String numberString = buttonName.replaceAll("\\D+","");
if(number.equals("Select a number")) {
button.setText("");
solveMap.put("key" + numberString, 0);
}
else {
button.setText(number);
solveMap.put("key" + numberString, Integer.valueOf(number));
}
}
/**
* This method recreates the board after the device's orientation has changed
* @param sudukoButtons Empty 2D Array of buttons
*/
private void loadButtonValue(Button[][] sudukoButtons) {
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++) {
String number = String.valueOf(solveMap.get("key" + i + j));
if (number.equals("0"))
sudukoButtons[i][j].setText("");
else
sudukoButtons[i][j].setText(number);
}
}
/**
* This method changes the activity and sends some parameters to the next activity
*/
private void loadResult(){
long time = System.currentTimeMillis();
int [][] resultBoard = new int[9][9];
resultBoard = populateBoard(resultBoard);
Intent intent = new Intent(this, SolverActivity.class);
Bundle bundle = new Bundle();
bundle.putSerializable("board", resultBoard);
intent.putExtras(bundle);
intent.putExtra("start", time);
startActivity(intent);
}
/**
* This method retrieves all the values from the buttons and places them in a 2D Array of the type int
* @param resultBoard Empty 2D Array
* @return A populated 2D Array, which the user wants to have solved
*/
private int[][] populateBoard(int[][] resultBoard){
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int number = solveMap.get("key" + i + j);
resultBoard[i][j] = number;
}
}
return resultBoard;
}
/**
* Clears all the buttons according the device orientation
* @param sudokuButtons 2D Array of Buttons which is linked to xml file (PORTRAIT or LANDSCAPE)
*/
private void clearAllButtons(Button[][] sudokuButtons){
solveMap.clear();
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
sudokuButtons[i][j].setText("");
solveMap.put("key" + i + j, 0);
}
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("solveMap", solveMap);
outState.putSerializable("verticalButtons", verticalButtons);
outState.putSerializable("landscapeButtons", landscapeButtons);
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
this.number = parent.getItemAtPosition(position).toString();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
public class SolverActivity extends AppCompatActivity {
private Button[][] buttons = new Button [9][9];
private Button backButton;
private int[][] board, solvedBoard;
private TextView timeView;
private long test;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_solver);
timeView = findViewById(R.id.result_time);
backButton = findViewById(R.id.back_button);
backButton.setOnClickListener(v -> onBackPressed());
board = (int[][]) getIntent().getExtras().getSerializable("board");
long time = getIntent().getLongExtra("start", 0);
if(savedInstanceState == null) {
SudokuSolver sudokuSolver = new SudokuSolver(board);
if (sudokuSolver.solve())
solvedBoard = sudokuSolver.getBoard();
else
solvedBoard = new int[9][9];
}
else{
solvedBoard = (int[][]) savedInstanceState.getSerializable("solvedBoard");
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
String buttonId = "button" + i + j;
int resId = getResources().getIdentifier(buttonId, "id", getPackageName());
buttons[i][j] = findViewById(resId);
buttons[i][j].setText(String.valueOf(solvedBoard[i][j]));
}
}
if (savedInstanceState == null)
test = System.currentTimeMillis();
else
test = savedInstanceState.getLong("test");
long stop = test - time;
timeView.append(stop + "ms");
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("solvedBoard", solvedBoard);
outState.putLong("test", test);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("solveMap", solveMap);
// The two lines beneath caused the app to crash
outState.putSerializable("verticalButtons", verticalButtons);
outState.putSerializable("landscapeButtons", landscapeButtons);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("solveMap", solveMap);
}