2014-01-30 3 views
4

대화 상자 조각을 사용하도록 내 응용 프로그램을 전환하려고하지만 대화 상자가 표시되어있는 동안 화면을 회전시킬 때 응용 프로그램이 중단됩니다. 아래에 설명 된 매우 간단한 응용 프로그램에서이를 재현 할 수 있습니다. 안드로이드 스튜디오에서 새 프로젝트를 만들고 그래서 같은 DialogFragment를 추가안드로이드 지원 화면 회전시 DialogFragment가 충돌 함

public class MainActivity extends ActionBarActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     if (savedInstanceState == null) { 
      getSupportFragmentManager().beginTransaction() 
        .add(R.id.container, new PlaceholderFragment()) 
        .commit(); 
     } 
     if (savedInstanceState == null) { 
      (new Handler()).postDelayed(new Runnable() { 
       @Override 
       public void run() { 
        AlertDialog dialog = new AlertDialog.Builder(MainActivity.this) 
          .setMessage("Alert") 
          .setTitle("My Alert") 
          .create(); 
        MyDialogFragment dialogFragment = new MyDialogFragment(); 
        dialogFragment.setDialog(dialog); 
        dialogFragment.show(getSupportFragmentManager(), "dialog"); 

       } 
      }, 1000); 
     } 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 
     if (id == R.id.action_settings) { 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 

    /** 
    * A placeholder fragment containing a simple view. 
    */ 
    public static class PlaceholderFragment extends Fragment { 

     public PlaceholderFragment() { 
     } 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
           Bundle savedInstanceState) { 
      View rootView = inflater.inflate(R.layout.fragment_main, container, false); 
      return rootView; 
     } 

     @Override 
     public void onActivityCreated(Bundle savedState) { 
      super.onActivityCreated(savedState); 
     } 
    } 

    public static class MyDialogFragment extends DialogFragment { 
     private Dialog mDialog; 

     public MyDialogFragment() { 
      super(); 
      mDialog = null; 
     } 

     @Override 
     public void onCreate(Bundle state) { 
      super.onCreate(state); 
     } 

     // Set the dialog to display 
     public void setDialog(Dialog dialog) { 
      mDialog = dialog; 
     } 

     // Return a Dialog to the DialogFragment. 
     @Override 
     public Dialog onCreateDialog(Bundle savedInstanceState) { 
      return mDialog; 
     } 
    } 
} 

이제 응용 프로그램을 실행하고, 대화 상자 (적재 후 1 초)를 표시 한 후, 화면을 회전 할 수 있습니다. 위의 초기 onCreate에 대해서만 대화 상자를 만듭니다. 여기

는 예외 임입니다 점점 ​​:

01-30 11:19:40.199 31986-31986/? E/AndroidRuntime﹕ FATAL EXCEPTION: main 
    Process: com.example.testdialogs, PID: 31986 
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.testdialogs/com.example.testdialogs.MainActivity}: java.lang.NullPointerException 
      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2215) 
      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2265) 
      at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3758) 
      at android.app.ActivityThread.access$900(ActivityThread.java:145) 
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1212) 
      at android.os.Handler.dispatchMessage(Handler.java:102) 
      at android.os.Looper.loop(Looper.java:136) 
      at android.app.ActivityThread.main(ActivityThread.java:5081) 
      at java.lang.reflect.Method.invokeNative(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:515) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:781) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
      at dalvik.system.NativeStart.main(Native Method) 
    Caused by: java.lang.NullPointerException 
      at android.support.v4.app.DialogFragment.onActivityCreated(DialogFragment.java:368) 
      at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1508) 
      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:947) 
      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104) 
      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086) 
      at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1884) 
      at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:566) 
      at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171) 
      at android.app.Activity.performStart(Activity.java:5241) 
      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2178) 
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2265) 
            at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3758) 
            at android.app.ActivityThread.access$900(ActivityThread.java:145) 
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1212) 
            at android.os.Handler.dispatchMessage(Handler.java:102) 
            at android.os.Looper.loop(Looper.java:136) 
            at android.app.ActivityThread.main(ActivityThread.java:5081) 
            at java.lang.reflect.Method.invokeNative(Native Method) 
            at java.lang.reflect.Method.invoke(Method.java:515) 
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:781) 
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
            at dalvik.system.NativeStart.main(Native Method) 
             
             
             
             

내 Gradle을 스크립트는 다음과 같습니다 : 새 프로젝트를 만들 때 단지 표준 빌드 스크립트와 최신 안드로이드를 사용

apply plugin: 'android' 

android { 
    compileSdkVersion 19 
    buildToolsVersion "19.0.1" 

    defaultConfig { 
     minSdkVersion 9 
     targetSdkVersion 19 
     versionCode 1 
     versionName "1.0" 
    } 

    compileOptions { 
     sourceCompatibility JavaVersion.VERSION_1_7 
     targetCompatibility JavaVersion.VERSION_1_7 
    } 
    buildTypes { 
     release { 
      runProguard false 
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 
     } 
    } 
} 

dependencies { 
    compile 'com.android.support:appcompat-v7:+' 
} 

항아리를 지원하십시오.

DialogFragment의 onCreate 메서드에서 setRetainInstance를 수행 할 수 있고 충돌이 발생하지 않지만 대화 상자가 회전 할 때 해제됩니다. 이것은 분명히 충돌보다 낫지 만 내가 찾고있는 것은 아닙니다.

DialogFragments를 선호하는 방법은 무엇인지 모르겠지만 Google에서 직접 샘플 코드 (Google 서비스 SDK)를 통해이 아이디어를 얻었습니다. 나는 그들이 똑같은 개념을 사용할 수 있도록 그들이 무엇을하고 있는지를 알았다고 생각했습니다.

답변

0

활동이 처음 작성되면 savedInstanceState은 저장 될 이전 상태가 없으므로 널입니다. 화면이 회전하면 작업이 삭제되고 이 다시 호출되어 일부 상태가 저장됩니다 (예 : DialogFragment 상태). 화면 회전이 인스턴스 저장 한 다음 onCreate(savedInstanceState)에 복원 할 때

그래서, 첫째로 당신의 savedInstaceState가 null 그래서 호출됩니다 if(savedInstanceState == null) 내부에 더 이상 널 아무것도하지 않고, 다음은 NullPointerException를 얻을.

이 문제를 해결이 검증을 제거하려면 다음

if(savedInstanceState == null){ 

    ///blablalba 

} 
+0

없음. 나는 이것을 실제로 알아 냈다. 아직 나는 대답을 아직 제출하지 않았다. DialogFragment의 onCreateDialog에 대화 상자를 만들어야합니다. 대화 상자로 전달하는 인스턴스가 문제를 일으키는 것 같습니다. 확실한 이유는 모르겠지만. –

+0

@MattWolfe Activity 클래스가 아닌 MyDialogFragment 클래스 내에서 이전 대화 상태로 작업해야합니다. 시도해 보셨습니까? –

2

난 내 자신의 질문에 대답하기 싫어을하지만 충돌에 대한 이유를 알아 냈어. DialogFragment의 onCreateDialog에서 실제로 내 Activity에서 설정하는 대신 대화 상자 생성을 수행해야합니다. 정확하지 않음 이유는입니다. 아마도 로테이션에서 안드로이드 시스템은 활동의 이전 인스턴스에 연결된 참조를 지 웁니다. 나는 그런 해결

public class MainActivity extends ActionBarActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     if (savedInstanceState == null) { 
      getSupportFragmentManager().beginTransaction() 
        .add(R.id.container, new PlaceholderFragment()) 
        .commit(); 
     } 
     if (savedInstanceState == null) { 
      (new Handler()).postDelayed(new Runnable() { 
       @Override 
       public void run() { 
        MyDialogFragment dialogFragment = new MyDialogFragment(); 
        dialogFragment.show(getSupportFragmentManager(), "dialog"); 

       } 
      }, 1000); 
     } 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 
     if (id == R.id.action_settings) { 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 

    /** 
    * A placeholder fragment containing a simple view. 
    */ 
    public static class PlaceholderFragment extends Fragment { 

     public PlaceholderFragment() { 
     } 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
           Bundle savedInstanceState) { 
      View rootView = inflater.inflate(R.layout.fragment_main, container, false); 
      return rootView; 
     } 

     @Override 
     public void onActivityCreated(Bundle savedState) { 
      super.onActivityCreated(savedState); 
     } 
    } 

    public static class MyDialogFragment extends DialogFragment { 
     public MyDialogFragment() { 
      super(); 
     } 

     @Override 
     public void onCreate(Bundle state) { 
      super.onCreate(state); 
     } 


     // Return a Dialog to the DialogFragment. 
     @Override 
     public Dialog onCreateDialog(Bundle savedInstanceState) { 
      return AlertDialog dialog = new AlertDialog.Builder(MainActivity.this) 
         .setMessage("Alert") 
         .setTitle("My Alert") 
         .create(); 
     } 
    } 
} 
2

: 충돌없이 회전에서 작동 업데이트 코드이 완전히 적합하지 않습니다하지만 난 아마 여기에

에서 대화 상자를 만드는 데 사용되는 데이터를 전달하여 작업 할 수 서브 클래 싱 DialogFragment 클래스와 오버라이드 (override) 다음 두 수명주기 콜백 메소드를 통해 문제 : 전혀 .. 내가 이전을 복원 할 새로운 대화 상자를 표시하지 않으 아니에요

@Override 
public void onCreate(@Nullable Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setRetainInstance(true); 
} 

@Override 
public void onDestroyView() { 
    if (getDialog() != null && getRetainInstance()) { 
     getDialog().setDismissMessage(null); 
    } 
    super.onDestroyView(); 
} 
관련 문제