注意:
下面显示的代码可能有点难以阅读,但我希望它可以提供帮助。对不起。
每当我按下HOME按钮并且我的应用程序变为背景时,我都会收到此错误。
java.lang.RuntimeException:Parcel:无法编组值 elektro_fr.newapplication.FragmentsActivity$3@a6c25e4
我是Android编程的新手,我想创建一个可以为我提供所有功能的类,而不是每次都实现它们。
我做了一个My_Activity课程:
package elektro_fr.my_android;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.GestureDetector;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.WindowManager;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
public abstract class My_Activity extends AppCompatActivity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener{
private int myLayout;
protected Bundle mySettings;
private boolean gesturesEnabled=false;
private GestureDetectorCompat myGestureDetector;
private boolean canStart=false;
private boolean menuEnabled=false;
private HashMap<String,Action> menuEntries;
protected List<My_Fragment> fragmentsList=new LinkedList<>();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myGestureDetector = new GestureDetectorCompat(this,this);
if (savedInstanceState==null){
canStart=true;
}
init();
setContentView(myLayout);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("LIST",menuEntries);
for (int counter=0;counter<fragmentsList.size();counter++){
getSupportFragmentManager().putFragment(outState,"FRAGMENT_SETTINGS_"+counter,fragmentsList.get(counter));
}
}
@Override
protected void onStart() {
super.onStart();
if (canStart) setGraphics();
canStart=false;
}
protected abstract void init();
protected abstract void setGraphics();
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState!=null){
menuEntries=(HashMap<String, Action>) savedInstanceState.getSerializable("LIST");
int size=getSupportFragmentManager().getFragments().size();
for (int counter=0;counter<size;counter++){
fragmentsList.add(counter,(My_Fragment)getSupportFragmentManager().getFragment(savedInstanceState,"FRAGMENT_SETTINGS_"+counter));
}
}
refreshState();
}
abstract protected void refreshState();
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return menuEnabled;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
if (menuEntries.get(item.getTitle())!=null){
menuEntries.get(item.getTitle()).doAction();
}
return menuEnabled;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if (menuEnabled){
if (menuEntries.size()!=0){
menu.clear();
int counter=0;
for (String s: menuEntries.keySet()){
menu.add(Menu.NONE,counter,Menu.NONE,s);
counter++;
}
}
}
return menuEnabled;
}
protected void setGestures(boolean enabled){
gesturesEnabled=enabled;
}
protected void setMenu(boolean enabled){
menuEnabled=enabled;
menuEntries=new HashMap<>();
}
protected HashMap<String, Action> getMenuEntries(){
return menuEntries;
}
public My_Fragment addFragment(Class<? extends My_Fragment> fragmentClass, int fragmentContainer, int fragmentID, Bundle fragmentArgs){
My_Fragment fragment = null;
try {
fragment = fragmentClass.newInstance();
}
catch (InstantiationException e){
}
catch (IllegalAccessException e){
e.printStackTrace();
}
fragment.setArguments(fragmentArgs);
getSupportFragmentManager().beginTransaction().add(fragmentContainer, fragment).commit();
fragmentsList.add(fragment);
return fragment;
}
protected My_Fragment getFragment(Class<? extends My_Fragment> fragmentClass){
for (My_Fragment f: fragmentsList){
if (fragmentClass.isInstance(f)){
return f;
}
}
return null;
}
public void removeFragment(My_Fragment fragment,boolean addToBackStack){
if (fragment.isAdded()){
FragmentTransaction transaction=getSupportFragmentManager().beginTransaction();
if (addToBackStack)transaction.addToBackStack(null);
transaction.remove(fragment);
transaction.commit();
getSupportFragmentManager().executePendingTransactions();
if (!addToBackStack)fragmentsList.remove(fragment);
}
}
protected void setFullScreen(boolean fullScreen){
WindowManager.LayoutParams attrs = getWindow().getAttributes();
if (fullScreen) {
attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
}
else {
attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
}
getWindow().setAttributes(attrs);
}
protected void hideActionBar(boolean hidden){
if (hidden){
getSupportActionBar().hide();
}
else getSupportActionBar().show();
}
protected void setLayout(int layoutID){
myLayout=layoutID;
}
public boolean onTouchEvent(MotionEvent event) {
if (gesturesEnabled){
this.myGestureDetector.onTouchEvent(event);
}
return true;
}
public boolean onSingleTapConfirmed(MotionEvent e) {
My_AndroidTools.KeyboardTools.closeInputKeyboard(getCurrentFocus());
return true;
}
public boolean onDoubleTap(MotionEvent e) {
return true;
}
public boolean onDoubleTapEvent(MotionEvent e) {
return true;
}
public boolean onDown(MotionEvent e) {
return true;
}
public void onShowPress(MotionEvent e) {
}
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return true;
}
public void onLongPress(MotionEvent e) {
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
}
这是FragmentsActivity,它扩展并实现了My_Activity:
package elektro_fr.newapplication;
import android.os.Bundle;
import android.util.Log;
import android.widget.RelativeLayout;
import elektro_fr.my_android.Action;
import elektro_fr.my_android.My_Activity;
import elektro_fr.my_android.My_Fragment;
import elektro_fr.newapplication.R;
public class FragmentsActivity extends My_Activity implements My_Fragment.fragmentOperations {
private MyTopFragment topFragment;
private MyBottomFragment bottomFragment;
@Override
protected void init() {
setLayout(R.layout.fragments);
setGestures(true);
setMenu(true);
}
@Override
protected void setGraphics() {
Bundle args=new Bundle();
args.putInt(MyTopFragment.LAYOUT_ID,R.layout.ts_fragment);
args.putInt(My_Fragment.CENTER_HORIZONTAL,RelativeLayout.CENTER_HORIZONTAL);
topFragment = (MyTopFragment) addFragment(MyTopFragment.class,R.id.MainLayout,R.layout.ts_fragment,args);
Bundle args2=new Bundle();
args2.putInt(My_Fragment.LAYOUT_ID,R.layout.bs_fragment);
args2.putInt(My_Fragment.LAYOUT_WIDTH,RelativeLayout.LayoutParams.MATCH_PARENT);
args2.putInt(My_Fragment.LAYOUT_HEIGHT,RelativeLayout.LayoutParams.WRAP_CONTENT);
args2.putInt(My_Fragment.BELOW, R.id.ts);
args2.putInt(My_Fragment.CENTER_HORIZONTAL,RelativeLayout.CENTER_HORIZONTAL);
bottomFragment = (MyBottomFragment) addFragment(MyBottomFragment.class,R.id.MainLayout,R.layout.bs_fragment,args2);
getMenuEntries().put("Menu Item #1", new Action() {
@Override
public void doAction() {
Log.i("Ciccio","you pressed 1");
}
});
getMenuEntries().put("Menu Item #2", new Action() {
@Override
public void doAction() {
Log.i("Ciccio","you pressed 2");
}
});
getMenuEntries().put("Menu Item #3", new Action() {
@Override
public void doAction() {
Log.i("Ciccio","you pressed 3");
}
});
}
protected void refreshState(){
topFragment = (MyTopFragment) getFragment(MyTopFragment.class);
bottomFragment = (MyBottomFragment) getFragment(MyBottomFragment.class);
}
@Override
public void ClickButtonOperation(Object[] arguments) {
switch((Integer)arguments[0]){
case 0:
bottomFragment.setText((String)arguments[1],(String)arguments[2]);
break;
}
}
}
这是My_Fragment类:
package elektro_fr.my_android;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.text.Layout;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
public abstract class My_Fragment extends Fragment {
public final static String LAYOUT_ID="layout_id";
public final static String LAYOUT_WIDTH="layout_width";
public final static String LAYOUT_HEIGHT="layout_height";
public final static String BELOW="layout_below";
public final static String ABOVE="layout_above";
public final static String ALIGN_PARENT_BOTTOM="align_parent_bottom";
public final static String CENTER_HORIZONTAL="center_horizontal";
private String[] params={
LAYOUT_ID,LAYOUT_WIDTH, LAYOUT_HEIGHT, ALIGN_PARENT_BOTTOM, CENTER_HORIZONTAL, BELOW, ABOVE
};
protected int fragmentLayout;
protected fragmentOperations myActivity;
protected Bundle mySettings;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState!=null){
mySettings=new Bundle();
mySettings.putAll(savedInstanceState);
}
else mySettings=getArguments();
fragmentLayout=mySettings.getInt(LAYOUT_ID);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
mySettings.putAll(savedInstanceState);
refreshState();
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
setState();
outState.putAll(mySettings);
}
public interface fragmentOperations{
void ClickButtonOperation(Object[] arguments);
}
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view=inflater.inflate(fragmentLayout,container,false);
int widthSettings=mySettings.getInt(params[1]);
int heightSettings=mySettings.getInt(params[2]);
view.setLayoutParams(new RelativeLayout.LayoutParams((widthSettings==0?RelativeLayout.LayoutParams.WRAP_CONTENT:widthSettings),(heightSettings==0?RelativeLayout.LayoutParams.WRAP_CONTENT:heightSettings)));
RelativeLayout.LayoutParams layoutConfig= (RelativeLayout.LayoutParams) view.getLayoutParams();
for (int counter=3;counter<params.length;counter++){
int settings=mySettings.getInt(params[counter]);
if (settings!=0){
if (counter==5){
layoutConfig.addRule(RelativeLayout.BELOW,settings);
}
else if (counter==6){
layoutConfig.addRule(RelativeLayout.ABOVE,settings);
}
else{
layoutConfig.addRule(settings);
}
}
}
init(view);
return view;
}
protected abstract void init(View v);
protected abstract void setState();
protected abstract void refreshState();
@Override
public void onAttach(Context context) {
super.onAttach(context);
myActivity=(fragmentOperations)getActivity();
}
}
修改
最后,我编辑的Action(界面),以实现Serializable:
package elektro_fr.my_android;
import java.io.Serializable;
public interface Action extends Serializable{
public void doAction();
}
这是错误:
流程:elektro_fr.newapplication,PID:24970 java.lang.RuntimeException:Parcelable遇到IOException编写可序列化对象(name = elektro_fr.newapplication.FragmentsActivity $ 3)
引起:
引起:java.io.NotSerializableException:elektro_fr.newapplication.FragmentsActivity
为什么我要在这个类中实现serializable?
答案 0 :(得分:0)
您尝试在OnSaveInstanceState中保存menuEntries,但类型为HashMap,并且此类型不可序列化。当你自己实现序列化时,只有原始可以保存或自定义对象。
答案 1 :(得分:0)
<强> SOLUTION:强>
遵循Johann67的想法:
好的我理解你的代码。你不能这样做。当你序列化一个 对象,只有字段被序列化并保存。但在这里你试着 序列化doAction()方法......您需要更改Action 宾语。也许你可以在HashMap上保存项目位置或 创建一个对象并将您的信息存储在字段中。
所以我修改了我的代码。
首先,我将menuEntries对象更改为String of List。
其次,我创建了一个新方法:
protected void dispatchItemAction(int itemID);
可以根据itemID覆盖以便在要执行的操作之间切换。
我修改了这个方法:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
dispatchItemAction(item.getItemId());
return menuEnabled;
}
protected void dispatchItemAction(int itemID){
}
现在,要添加菜单项:
protected void addMenuItems(){
getMenuEntries().add("Menu Item #1");
getMenuEntries().add("Menu Item #2");
getMenuEntries().add("Menu Item #3");
}
@Override
protected void dispatchItemAction(int itemID) {
switch(itemID){
case 0:
Log.i("Log","Pressed #1.");
break;
case 1:
Log.i("Log","Pressed #2.");
break;
case 2:
Log.i("Log","Pressed #3.");
break;
}
}