2016-06-14 3 views
0

참고 마샬링 할 수 없습니다 :안드로이드의 RuntimeException : 소포 : 값을

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

을 내가 HOME 버튼을 누를 때마다 나는이 오류가 내 응용 프로그램은 배경을 간다.

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

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

편집 :

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 클래스

,

마지막으로,이 순서대로 편집 동작 (인터페이스) 직렬화 구현 :

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

의해 발생 :

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

해야하는 이유

package elektro_fr.my_android; 

import java.io.Serializable; 

public interface Action extends Serializable{ 

    public void doAction(); 
} 

오류이며 이 클래스에서 serializable을 구현합니까?

+1

StackOverflow의 고전 포럼처럼 작동하지 않습니다, 그것은 Q & A 사이트입니다.질문을 수정하고 제목과 해결 방법에서 _ (해결 된) _을 제거하십시오. 아래의 _Answer Your Question_ 버튼을 사용하여 솔루션을 추가하십시오. 그리고 미래에는 문제를 일으키는 데 필요한 최소한의 코드 만 게시하는 것이 좋습니다. – perissf

+0

@perissf 해줘서 고마워. 내 게시물을 편집했습니다. 불행히도, 나는 어디에 문제가 될지 몰랐다. 그래서 나는 전체 코드를주는 것이 좋은 생각이었을 것이라고 생각했다. –

답변

0

OnSaveInstanceState에 menuEntries를 저장하려고했지만 형식이 HashMap이고이 형식이 serialize되지 않습니다. 사용자가 직접 직렬화를 구현할 때 기본 객체 만 저장하거나 사용자 정의 객체 일 수 있습니다.

+0

내가 아는 바로는 HashMap 클래스는 serializable을 구현합니다. –

+0

"Action"은 직렬화 가능합니까? – Johann67

+0

"Action"에 "implements Serializable"이 추가되었습니다. 오류가 변경되었습니다. 수정 사항에 대한 게시물을 참조하십시오. –

0

해결책 : Johann67 아이디어에 따라

는 :

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.

그래서 난 내 코드를 수정했습니다.

우선, 내 menuEntries 객체를 List of String으로 변경했습니다. 할 행동 사이를 전환하기 위해 오버라이드 (override) 할 수

protected void dispatchItemAction(int itemID); 

, 항목 ID를 기반으로 :

둘째, 나는 새로운 방법을 만들었습니다.

그리고 난이 방법 수정 :

지금
@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; 
    } 
}