2013-02-01 77 views
5

我的DialogFragment拋出ClassCastException如果從片段調用,而它正常工作,如果從一個活動調用。我已經查看了幾個類似問題的其他問題,基本上這些問題都與進口有關,但是在我的實施中,我還沒有能夠解決這個問題。這是我對DialogFragment的實現。DialogFragment拋出ClassCastException如果從片段調用

 
import android.app.AlertDialog; 
import android.app.Dialog; 
import android.app.DialogFragment; 

public class HotspotScanDialog extends DialogFragment { 

    SetupHotspotDialogListener mListener; 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     ... 

     .setAdapter(hotspotAdapter, new DialogInterface.OnClickListener() { 
      @Override 
      public void onClick(DialogInterface dialog, int which) { 
       mListener.onHotspotSelectedListener(hotspotAdapter.getItem(
         which).toString()); 
      } 
     })... 
    } 

    public interface SetupHotspotDialogListener { 
     public void onHotspotSelectedListener(String selection); 

    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 

     try { 
      mListener = (SetupHotspotDialogListener) activity; 
     } catch (ClassCastException ignore) { 
      // Just to make sure if anyone will be pointing at my throwing 
      // ClassCastException myself I have tried without this code as well. 
      throw new ClassCastException(activity.toString() 
        + " must implement NoticeDialogListener"); 
     } 
    } 
} 

這是我的片段,其使用上述DialogFragment:

 
import android.app.AlertDialog; 
import android.app.DialogFragment; 
import android.support.v4.app.Fragment; 
import com.xxx.yyy.ui.compontent.dialog.HotspotScanDialog; 
import com.xxx.yyy.ui.compontent.dialog.HotspotScanDialog.SetupHotspotDialogListener; 

public class SmartMode extends Fragment implements SetupHotspotDialogListener { 

    private void showWifiSelectionDialog() { 
     DialogFragment setupWifiSelectionDialog = new HotspotScanDialog(); 

     /* 
     * using getFragmentManager() only says "The method 
     * show(FragmentManager, String) in the type DialogFragment is not 
     * applicable for the arguments (FragmentManager, String)" 
     */ 

     setupWifiSelectionDialog.show(getActivity().getFragmentManager(), 
       Keys.TAG.toString()); 
    } 

    @Override 
    public void onHotspotSelectedListener(String selection) { 
     // Log.d(TAG,selection); 
    } 
} 

這是錯誤日誌:

02-01 13:11:32.750:E/AndroidRuntime( 15061):FATAL EXCEPTION:main 02-01 13:11:32.750:E/AndroidRuntime(15061):java.lang.ClassCastException:[email protected]必須實現NoticeDialogListener 02-01 13:11: 32.750:E/An droidRuntime(15061):at com.xxx.yyy.ui.compontent.dialog.HotspotScanDialog.onAttach(HotspotScanDialog.java:122) 02-01 13:11:32.750:E/AndroidRuntime(15061):at android.app。 FragmentManagerImpl.moveToState(FragmentManager.java:787) 02-01 13:11:32.750:E/AndroidRuntime(15061):at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035) 02-01 13:11: 32.750:E/AndroidRuntime(15061):at android.app.BackStackRecord.run(BackStackRecord.java:635) 02-01 13:11:32.750:E/AndroidRuntime(15061):at android.app.FragmentManagerImpl.execPendingActions FragmentManager.java:1397) 02-01 13:11:32.750:E/AndroidRuntime(15061):at android.app.FragmentManagerImpl $ 1.run(FragmentManager.java:426) 02-01 13:11:32.750:E/AndroidRuntime(15061):at android.os.Handler.handleCallback(Handler.java:615) 02-01 13:11:32.750:E/AndroidRuntime(15061):在android.os.Handler.dispatchMessage(Handler.java:92) 02-01 13:11:32.750:E/AndroidRuntime(15061):at android.os.Looper.loop(Looper.java:137) 02-01 13:11:32.750:E/AndroidRuntime(15061):at android.app.ActivityThread.main(ActivityThread.java:4898) 02-01 13:11:32.750:E/AndroidRuntime(15061):在java.lang.reflect.Method.invokeNative(本地方法) 02-01 13:11:32.750:E/AndroidRuntime(15061):在java.lang.reflect .Method.invoke(Method.java:511) 02-01 13:11:32.750:E/AndroidRuntime(15061):at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:1006) 02-01 13:11:32.750:E/AndroidRuntime(15061):at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773) 02-01 13:11:32.750:E/Android運行時(15061):在dalvik.system.NativeStart.main(本機方法)

我想知道是否有人可以提供有關此問題的提示。

回答

10

docs

onAttach(Activity) called once the fragment is associated with its activity. 

在你的代碼

mListener = (SetupHotspotDialogListener) activity; 

線拋出ClassCastException因爲你的活動沒有實現SetupHotspotDialogListener接口。 (Fragment與包含它的活動直接相關,因爲DialogFragment延伸Fragment)。

再從docs

In some cases, you might need a fragment to share events with the activity. A good way to do that is to define a callback interface inside the fragment and require that the host activity implement it. When the activity receives a callback through the interface, it can share the information with other fragments in the layout as necessary.

所以,如果你想創建FragmentDialogFragment我建議通過回調來組織它的活動:

  1. 創建回調接口到您的SmartModeFragment類(像你進入dialogFragment一樣)用一種方法如createDialogRequest()
  2. 讓您的活動實現該接口
  3. 然後,當你需要創建對話框,從FragmentActivity
  4. 地方「顯示對話框邏輯」發送回調到Activity

它看起來像片段詢問活動創建對話框,活動顯示對話框。

編輯: 我想我已經找到了更好的實現你所需要的東西。我已經寫了一個簡單的例子,從片段創建fragment dialog,將fragment dialog回調事件分段。

活動:

public class MyFragmentActivity extends FragmentActivity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_my_fragment); 

    // first start of activity 
    if (savedInstanceState == null) { 
     // put fragment to activity layout 
     MyFragment fragment = new MyFragment(); 
     FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
     ft.replace(R.id.fragmentContainer, fragment, "fragment"); 
     ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 
     ft.commit(); 
    } 
}} 

片段:

public class MyFragment extends Fragment implements MyDialogInterface { 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    super.onCreateView(inflater, container, savedInstanceState); 

    View fragmentView = inflater.inflate(R.layout.fragment, null); 

    // button which shows dialog 
    Button showDialogButton = (Button) fragmentView.findViewById(R.id.showDialog); 
    showDialogButton.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      // create fragment dialog. 
      FragmentDialog dialog = FragmentDialog.getInstance(MyFragment.this); 
      dialog.show(getActivity().getSupportFragmentManager(), "dialog"); 
     } 
    }); 
    return fragmentView; 
} 

@Override 
public void onClickEvent() { 
    // receive click events from dialog fragment 
    Log.e(getClass().getSimpleName(), "onClickEvent"); 
} 

}

FragmentDialog:

public class FragmentDialog extends DialogFragment { 

public interface MyDialogInterface extends Serializable { 
    public void onClickEvent(); 
} 

private MyDialogInterface callbackListener; 

/** 
* dialogInterface - instance of MyDialogInterface which will handle 
* callback events 
*/ 
public static FragmentDialog getInstance(MyDialogInterface dialogInterface) { 
    FragmentDialog fragmentDialog = new FragmentDialog(); 

    // set fragment arguments 
    Bundle args = new Bundle(); 
    args.putSerializable("dialogInterface", dialogInterface); 
    fragmentDialog.setArguments(args); 

    return fragmentDialog; 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setStyle(STYLE_NO_TITLE, 0); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

    View pushDialogView = getActivity().getLayoutInflater().inflate(R.layout.fragment_dialog, null); 

    // get reference to MyDialogInterface instance from arguments 
    callbackListener = (MyDialogInterface) getArguments().getSerializable("dialogInterface"); 

    Button cancelButton = (Button) pushDialogView.findViewById(R.id.button); 
    cancelButton.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      // send click event 
      callbackListener.onClickEvent(); 
     } 
    }); 

    return pushDialogView; 
}} 

我用支持體4文庫片段(android.support.v4.app.Fragmentandroid.support.v4.app.DialogFragmentandroid.support.v4.app.FragmentActivity)。

和佈局:

activity_my_fragment.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/fragmentContainer" 
android:layout_width="match_parent" 
android:layout_height="match_parent" /> 

fragment.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:background="#a00" 
android:orientation="vertical" > 
<Button 
    android:id="@+id/showDialog" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="show doalog" /> 
</LinearLayout> 

fragment_dialog.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:background="#fe3" 
android:orientation="vertical" > 

<Button 
    android:id="@+id/button" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="click me" /> 
</LinearLayout> 

的想法是發送引用到會捕獲回調事件的接口。

+0

如果你看看我的代碼,它清楚地表明「公共類SmartMode擴展Fragment實現了SetupHotspotDialogListener」。這段代碼完全適用於活動,它的回調接口也被實現。你的意思是我必須將接口實現爲承載這些碎片的主要活動嗎? – Milan

+0

我的想法並不令人興奮,但是在承載這些碎片的活動中實現這些接口解決了我的問題。儘管如果您試圖將對話列表放入調用該對話框的實際片段中,這可能會受到限制。無論如何感謝提示。 – Milan

+1

我編輯了我的答案。我認爲我的答案的第一部分不是最好的解決方案。 –

相關問題