2016-06-14 26 views
0

HINWEIS Marschall:Android Runtimeexception: Paket: unable Wert

The code shown below may be a bit hard to read, but i hope it can help. Sorry for that.

ich diese Fehlermeldung erhalten, wenn i HOME-Taste drücken und meine app geht Hintergrund.

java.lang.RuntimeException: Parcel: unable to marshal value [email protected]

Ich bin neu in Android-Programmierung, und ich möchte eine Klasse erstellen, die mir alle Funktionen bieten können sie jedes Mal ohne Umsetzung.

ich eine My_Activity Klasse gemacht:

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; 
    } 
} 

Dies ist FragmentsActivity, die My_Activity erweitert und implementiert:

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; 
     } 
    } 
} 

Dies ist My_Fragment Klasse:

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(); 
    } 
} 

EDIT:

Schließlich Aktion (Schnittstelle), die ich um bearbeitet Serializable zu implementieren:

package elektro_fr.my_android; 

import java.io.Serializable; 

public interface Action extends Serializable{ 

    public void doAction(); 
} 

Dies ist der Fehler:

Process: elektro_fr.newapplication, PID: 24970 java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = elektro_fr.newapplication.FragmentsActivity$3)

Verursacht durch:

Caused by: java.io.NotSerializableException: elektro_fr.newapplication.FragmentsActivity

warum sollte Ich implementiere Serializable in dieser Klasse?

+1

Stackoverflow wie ein klassisches Forum nicht funktioniert, ist es eine Q & A-Website.Bitte editiere die Frage und entferne das _ (gelöst) _ aus dem Titel und der Lösung. Fügen Sie die Lösung mithilfe der Schaltfläche "Ihre Frage beantworten" unten hinzu. Und denken Sie für die Zukunft daran, nur die minimale Menge an Code zu posten, die notwendig ist, um das Problem auszulösen. – perissf

+0

@perissf Danke, dass du es sagst. Ich habe meinen Beitrag bearbeitet. Leider wusste ich nicht, wo das Problem sein könnte, also dachte ich, es wäre eine gute Idee gewesen, den ganzen Code zu geben. –

Antwort

0

Sie versuchen, Menüeinträge in OnSaveInstanceState zu speichern, aber der Typ ist HashMap, und dieser Typ ist nicht serialisierbar. Nur primitive Objekte können ein gespeichertes oder benutzerdefiniertes Objekt sein, wenn Sie die Serialisierung selbst implementieren.

+0

Soweit ich weiß, implementiert HashMap Klasse serializable .. –

+0

Und ist "Action" serialisierbar? – Johann67

+0

Hinzugefügt "implementiert Serializable" zu "Aktion". Der Fehler hat sich geändert: siehe Beitrag zur Bearbeitung. –

0

LÖSUNG:

Johann67 Idee folgend:

Ok I understand your code. You can't do that. When you serialize an object, only the fields are serialized and save. But here you try to serialize the doAction() method... You need to change the Action object. Maybe you can just save the item position on your HashMap or create an object and store your information in the fields.

So modifizierte ich meinen Code.

Zuerst änderte ich mein menuEntries-Objekt in eine String-Liste.

Zweitens habe ich eine neue Methode:

protected void dispatchItemAction(int itemID); 

, die um zwischen den Aktionen zu wechseln außer Kraft gesetzt werden können, um zu tun, auf der Grundlage der itemID.

Und ich diese Methode geändert:

@Override 
    public boolean onOptionsItemSelected(MenuItem item) { 

     super.onOptionsItemSelected(item); 

     dispatchItemAction(item.getItemId()); 

     return menuEnabled; 
    } 

    protected void dispatchItemAction(int itemID){ 


    } 

jetzt, Menüpunkte hinzuzufügen:

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; 
    } 
}