5

पर इस क्रिया को निष्पादित नहीं कर सकता है इसलिए मैं इस समस्या को हल करने का तरीका समझने की कोशिश कर रहा हूं, लेकिन मैं इसे वास्तव में ठीक नहीं कर सकता। अभी मेरे पास एक बटन के साथ एक टुकड़ा है। जब आप इस बटन को दबाते हैं तो यह ठीक/रद्द बटन के साथ एक कस्टम DialogFragment लॉन्च करेगा।किसी अन्य खंड से संवादफ्रेषण लॉन्च करना: IllegalStateException: SaveInstanceState

यदि मैं ठीक बटन दबाता हूं तो यह एक और कस्टम DialogFragment लॉन्च करेगा, इस बार यह ProgressDialog खंड है। समस्या यह है कि, जब मैं घुमाता हूं तो ठीक/रद्द संवाद प्रकट होता है और फिर ProgressDialog खंड को कॉल करने के लिए ठीक बटन दबाएं, मुझे यह त्रुटि मिलती है। अगर मैं केवल घुमाता हूं, जबकि प्रगतिशीलता खंड दिखा रहा है तो कोई समस्या नहीं है। मैं समर्थन पैकेज v4 का उपयोग कर रहा हूँ। यहाँ वर्गों है:

MainActivity:

public class MainActivity extends FragmentActivity implements OnFragmentAttachedListener, Callbacks{ 

boolean mResumed = false; 

@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    FragmentManager fragmentManager = getSupportFragmentManager(); 
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 

    fragmentTransaction.add(R.id.main_id, new EmptyFragmentWithCallbackOnResume()); 
    fragmentTransaction.commitAllowingStateLoss(); 

} 
@Override 
public void onTaskFinished() 
{ 
    // Hooray. A toast to our success. 
    Toast.makeText(this, "Task finished!", Toast.LENGTH_LONG).show(); 
    // NB: I'm going to blow your mind again: the "int duration" parameter of makeText *isn't* 
    // the duration in milliseconds. ANDROID Y U NO ENUM? 
} 

@Override 
public void OnFragmentAttached() { 

} } 

okcancel dialogfragment:

public class OkCancelDialogFragment<T> extends DialogFragment { 

public final static String TITLE="title"; 

private OkCancelDialogEvents<T> buttonEvents; 
private T[] params; 


public OkCancelDialogFragment(String title, OkCancelDialogEvents<T> buttonEvents, T... params) { 

    this.buttonEvents=buttonEvents; 

    Bundle args = new Bundle(); 
    args.putString(TITLE, title); 
    this.setArguments(args); 

    this.params=params; 

} 


@Override 
public void onCreate(Bundle savedInstanceState) { 
    // TODO Auto-generated method stub 
    super.onCreate(savedInstanceState); 
    this.setRetainInstance(true); 
} 


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


@Override 
public Dialog onCreateDialog(Bundle savedInstanceState) { 

    String title = getArguments().getString(TITLE); 
    return new AlertDialog.Builder(getActivity()) 
    //.setIcon(R.drawable.alert_dialog_icon) 
    .setTitle(title) 
    .setPositiveButton("ok", 
     new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int whichButton) { 
       buttonEvents.onPositiveClick(params); 
      } 
     } 
    ) 
    .setNegativeButton("cancel", 
     new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int whichButton) { 
       buttonEvents.onNegativeClick(); 
      } 
     } 
    ) 
    .create(); }} 

प्रगति संवाद टुकड़ा:

public class TaskFragment extends DialogFragment{ 
// The task we are running. 
GenericTask<?,?> mTask; 
ProgressDialog mProgressDialog; 
String title, message; 

public void setTask(MyTask task) 
{ 
    mTask = task; 

    // TellsetFragment the AsyncTask to call updateProgress() and taskFinished() on this fragment. 

    mTask.setFragment(this); 
} 


public void setTitleMessage(String title, String message){ 
    this.title=title; 
    this.message=message;  
} 


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

    // Retain this instance so it isn't destroyed when MainActivity and 
    // MainFragment change configuration. 
    setRetainInstance(true); 

} 

@Override 
public Dialog onCreateDialog(Bundle savedInstanceState) { 

    mProgressDialog= new ProgressDialog(getActivity()); 
    mProgressDialog.setTitle(title); 
    mProgressDialog.setMessage(message); 
    mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
    mProgressDialog.setCanceledOnTouchOutside(false); 

    return mProgressDialog; 
} 

// This is to work around what is apparently a bug. If you don't have it 
// here the dialog will be dismissed on rotation, so tell it not to dismiss. 
@Override 
public void onDestroyView() 
{ 
    if (getDialog() != null && getRetainInstance()) 
     getDialog().setDismissMessage(null); 
    super.onDestroyView(); 
} 

// Also when we are dismissed we need to cancel the task. 
@Override 
public void onDismiss(DialogInterface dialog) 
{ 
    super.onDismiss(dialog); 
    // If true, the thread is interrupted immediately, which may do bad things. 
    // If false, it guarantees a result is never returned (onPostExecute() isn't called) 
    // but you have to repeatedly call isCancelled() in your doInBackground() 
    // function to check if it should exit. For some tasks that might not be feasible. 
    if (mTask != null) 
     mTask.cancel(false); 

    // You don't really need this if you don't want. 
    if (getTargetFragment() != null) 
     getTargetFragment().onActivityResult(MainFragment.TASK_FRAGMENT, Activity.RESULT_CANCELED, null); 
} 

@Override 
public void onResume() 
{ 
    super.onResume(); 
    // This is a little hacky, but we will see if the task has finished while we weren't 
    // in this activity, and then we can dismiss ourselves. 
    if (mTask == null) 
     dismiss(); 
} 

// This is called by the AsyncTask. 
public void updateProgress(int percent) 
{ 
    mProgressDialog.setProgress(percent); 
} 

// This is also called by the AsyncTask. 
public void taskFinished() 
{ 
    // Make sure we check if it is resumed because we will crash if trying to dismiss the dialog 
    // after the user has switched to another app. 
    if (isResumed()) 
     dismiss(); 

    // If we aren't resumed, setting the task to null will allow us to dimiss ourselves in 
    // onResume(). 
    mTask = null; 

    // Tell the fragment that we are done. 
    if (getTargetFragment() != null) 
     getTargetFragment().onActivityResult(MainFragment.TASK_FRAGMENT, Activity.RESULT_OK, null); 
} 

}

mainFragment:

public class MainFragment extends Fragment implements OkCancelDialogEvents<Void>, OnClickListener{ 
// This code up to onDetach() is all to get easy callbacks to the Activity. 
private Callbacks mCallbacks = sDummyCallbacks; 

private static Callbacks sDummyCallbacks = new Callbacks() 
{ 
    public void onTaskFinished() { } 
}; 

@Override 
public void onAttach(Activity activity) 
{ 
    super.onAttach(activity); 
    if (!(activity instanceof Callbacks)) 
    { 
     throw new IllegalStateException("Activity must implement fragment's callbacks."); 
    } 
    mCallbacks = (Callbacks) activity; 
} 

@Override 
public void onDetach() 
{ 
    super.onDetach(); 
    mCallbacks = sDummyCallbacks; 
} 

// Save a reference to the fragment manager. This is initialised in onCreate(). 
private FragmentManager mFM; 

// Code to identify the fragment that is calling onActivityResult(). We don't really need 
// this since we only have one fragment to deal with. 
static final int TASK_FRAGMENT = 0; 

// Tag so we can find the task fragment again, in another instance of this fragment after rotation. 
static final String TASK_FRAGMENT_TAG = "task"; 

@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    //this.setRetainInstance(true); 
    super.onCreate(savedInstanceState); 
    // At this point the fragment may have been recreated due to a rotation, 
    // and there may be a TaskFragment lying around. So see if we can find it. 
    mFM = getFragmentManager(); 
    // Check to see if we have retained the worker fragment. 
    TaskFragment taskFragment = (TaskFragment)mFM.findFragmentByTag(TASK_FRAGMENT_TAG); 

    if (taskFragment != null) 
    { 
     // Update the target fragment so it goes to this fragment instead of the old one. 
     // This will also allow the GC to reclaim the old MainFragment, which the TaskFragment 
     // keeps a reference to. Note that I looked in the code and setTargetFragment() doesn't 
     // use weak references. To be sure you aren't leaking, you may wish to make your own 
     // setTargetFragment() which does. 
     taskFragment.setTargetFragment(this, TASK_FRAGMENT); 
    } 

} 

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

@Override 
public void onActivityCreated(Bundle savedInstanceState) { 

    super.onActivityCreated(savedInstanceState); 
    if(savedInstanceState!=null) 
     Toast.makeText(getActivity(), savedInstanceState.getString("documents"), Toast.LENGTH_SHORT).show(); 
} 

@Override 
public void onSaveInstanceState(Bundle outState) { 

    super.onSaveInstanceState(outState); 
    outState.putString("documents", "teste"); 
} 

@Override 
public void onViewCreated(View view, Bundle savedInstanceState) 
{ 
    super.onViewCreated(view, savedInstanceState); 

    // Callback for the "start task" button. I originally used the XML onClick() 
    // but it goes to the Activity instead. 
    view.findViewById(R.id.taskButton).setOnClickListener(this); 
} 

@Override 
public void onClick(View v) 
{ 

    OkCancelDialogFragment<Void> dialog = new OkCancelDialogFragment<Void>("Teste", this); 
    dialog.setTargetFragment(this, 2); 
    dialog.show(getFragmentManager(), "basic_dialog"); 


} 

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) 
{ 
    if (requestCode == TASK_FRAGMENT && resultCode == Activity.RESULT_OK) 
    { 
     // Inform the activity. 
     mCallbacks.onTaskFinished(); 
    } 
} 


@Override 
public void onPositiveClick(Void... params) { 

    // We only have one click listener so we know it is the "Start Task" button. 

    // We will create a new TaskFragment. 
    TaskFragment taskFragment = new TaskFragment(); 
    // And create a task for it to monitor. In this implementation the taskFragment 
    // executes the task, but you could change it so that it is started here. 

    MyTask task=new MyTask(); 
    task.execute("one","two"); 

    taskFragment.setTask(task); 
    taskFragment.setTitleMessage("File Download", "Downloading..."); 
    // And tell it to call onActivityResult() on this fragment. 
    taskFragment.setTargetFragment(this, TASK_FRAGMENT); 
    // Show the fragment. 
    // I'm not sure which of the following two lines is best to use but this one works well. 
    taskFragment.show(mFM, TASK_FRAGMENT_TAG); 
    //mFM.beginTransaction().add(taskFragment, TASK_FRAGMENT_TAG).commit(); 

} 

@Override 
public void onNegativeClick() { 


}} 

यहाँ त्रुटियों है:

12-12 11:24:52.144: E/AndroidRuntime(2451): FATAL EXCEPTION: main 
12-12 11:24:52.144: E/AndroidRuntime(2451): java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1327) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1338) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at android.support.v4.app.DialogFragment.show(DialogFragment.java:127) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at com.example.progressdialog.MainFragment.onPositiveClick(MainFragment.java:149) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at com.example.progressdialog.MainFragment.onPositiveClick(MainFragment.java:1) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at com.example.progressdialog.OkCancelDialogFragment$1.onClick(OkCancelDialogFragment.java:56) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:196) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at android.os.Handler.dispatchMessage(Handler.java:99) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at android.os.Looper.loop(Looper.java:123) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at android.app.ActivityThread.main(ActivityThread.java:4627) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at java.lang.reflect.Method.invokeNative(Native Method) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at java.lang.reflect.Method.invoke(Method.java:521) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
12-12 11:24:52.144: E/AndroidRuntime(2451):  at dalvik.system.NativeStart.main(Native Method) 
+0

क्या आपके टुकड़ों में 'setRetainInstance' का उपयोग करने का कोई कारण है? – Luksprog

+0

वैसे मैं केवल संवादफलक पर setReatainInstance का उपयोग कर रहा हूं। अगर वे झूठ पर सेट हैं तो वे घूर्णन पर गायब नहीं होंगे? – Maxrunner

+0

आप अपने लिए कोशिश कर सकते हैं और देख सकते हैं :)। SetRetainInstance का मतलब है कि विखंडन का उदाहरण कॉन्फ़िगरेशन परिवर्तन के बाद बनाए रखा जाएगा ताकि टुकड़ा फिर से चालू नहीं किया जाएगा। – Luksprog

उत्तर

1

अनुकूलता पैकेज (जो अभी तक हल नहीं किया जाता है) के साथ एक बग हो रहा है यही कारण है कि। वैसे भी, आप टुकड़ों के बीच संचार को बेहतर तरीके से संभालने के लिए अपने कोड को संशोधित करके उस बग से बच सकते हैं। मैंने आपके नमूना प्रोजेक्ट को संशोधित किया है (जिसे here पाया जा सकता है)। इसके बारे में, मुझे नहीं पता कि आपका नमूना कितना आसान है, लेकिन यदि सभी कॉलबैक गतिविधि पर वापस आते हैं तो आपको गतिविधि वर्ग को टुकड़ों को संभालना चाहिए (उदाहरण के लिए संवाद शुरू करना) और उनके बीच संचार, क्योंकि यह " देखता है "और इसमें सभी टुकड़ों की स्थिति जानता है।

+0

हाय उत्तर के लिए धन्यवाद। मैं इसे बाद में आज cjeck :) – Maxrunner

+0

हाय वहाँ Luksprog। मैं आपके कोड में बदलाव की जांच कर रहा हूं और ऐसा लगता है कि ओकैंकेल्डियलॉग के लिए कन्स्ट्रक्टर के साथ मुख्य समस्या थी, क्या आप इसकी पुष्टि कर सकते हैं? आप कहते हैं कि मुझे इसे पैराम पास करने के लिए बंडल का उपयोग करना चाहिए? क्या यह वास्तव में मुख्य मुद्दा था? मैंने भी ' दूसरे संवाद खंड में कॉल में टिप्पणी को समझ में नहीं आया। क्या आप विस्तार से समझा सकते हैं? संबंध, – Maxrunner

+0

@Maxrunner नहीं, त्रुटि एक बग के कारण थी। मैंने कुछ बदलाव किए हैं क्योंकि आपके टुकड़े ठीक तरह से नहीं बनाए गए थे और अच्छी तरह से संवाद नहीं किया था। आपके पास पैरामीटर के साथ कन्स्ट्रक्टर के साथ 'फ्रैगमेंट' नहीं होना चाहिए क्योंकि एंड्रॉइड उस टुकड़े को तत्काल करने में सक्षम नहीं होगा जब आपको इसकी आवश्यकता होती है (आपने इसे नहीं देखा क्योंकि आपने 'setRetainInstance (true)' का उपयोग किया था)। हां, पैरामीटर को पारित करने के लिए आपको 'बंडल' का उपयोग करना चाहिए, यदि आपके पास कुछ भी भारी है तो मैंने' ओकेकैंकेलडिअलोग एवेन्ट्स 'इंटरफ़ेस में एक अतिरिक्त विधि जोड़ दी है, जिसे' ओकेकैंकेलडिअलॉगफ्रेगमेंट 'अतिरिक्त डेटा प्राप्त करने के लिए' बटोनवेंट्स 'पर कॉल कर सकता है। – Luksprog