2

Eclipse 生成的主细节流在扩展的类中有一些回调魔法ListFragment——我说魔法是因为当你是 Android 和 Java 菜鸟时,这就是它的样子:)

鉴于下面的代码,有人可以为我回答几个问题:

  1. onAttach方法是ListFragment做什么用的mCallbacks = (Callbacks) activity
  2. 哪个方法在方法中onItemSelected被调用,需要实现的方法还是在方法中?onListItemClickListFragmentonItemSelectedFragmentActivity
  3. 所有这些onItemSelected方法都采用 an idof 类型String(因为DummyContent idis a String)。如果我更改DummyContent id为 a ,我需要更改long哪些方法?onItemSelected我试着换了一个,FragmentActivity但这有@Override,所以我不被允许:(

谢谢

public class RecordingListFragment extends ListFragment {

    private static final String STATE_ACTIVATED_POSITION = "activated_position";

    private Callbacks mCallbacks = sDummyCallbacks;
    private int mActivatedPosition = ListView.INVALID_POSITION;

    public interface Callbacks {

        public void onItemSelected(String id);
    }

    private static Callbacks sDummyCallbacks = new Callbacks() {
        @Override
        // NEEDS IMPLEMENTATION - i guess????
        public void onItemSelected(String id) {
        }
    };

...

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

    @Override
    public void onListItemClick(ListView listView, View view, int position, long id) {
        super.onListItemClick(listView, view, position, id);
        mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
    }

...

}

还有一个文件...

public class RecordingListActivity extends FragmentActivity
        implements RecordingListFragment.Callbacks {

    private boolean mTwoPane;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recording_list);
        getActionBar().setDisplayHomeAsUpEnabled(true);

        if (findViewById(R.id.recording_detail_container) != null) {
            mTwoPane = true;
            ((RecordingListFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.recording_list))
                    .setActivateOnItemClick(true);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                NavUtils.navigateUpFromSameTask(this);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onItemSelected(String id) {
        if (mTwoPane) {
            Bundle arguments = new Bundle();
            arguments.putString(RecordingDetailFragment.ARG_ITEM_ID, id);
            RecordingDetailFragment fragment = new RecordingDetailFragment();
            fragment.setArguments(arguments);
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.recording_detail_container, fragment)
                    .commit();

        } else {
            Intent detailIntent = new Intent(this, RecordingDetailActivity.class);
            detailIntent.putExtra(RecordingDetailFragment.ARG_ITEM_ID, id);
            startActivity(detailIntent);
        }
    }
}
4

1 回答 1

4

ListFragment 的 onAttach 方法对 mCallbacks = (Callbacks) 活动有什么作用?

onAttach回调中,Activity/ FragmentActivityFragment将被绑定/使用)被传递给该Fragment实例(通过活动参数)。该行只是将其转换为稍后在(见下文)中使用Activity的接口。您必须实现该接口,否则代码将由于先前的条件而失败。基本上,方法中的代码说:“将使用此片段的 Activity 必须实现 Callbacks 接口,否则代码将因 IllegalStateException 而失败”CallbacksFragmentActivity ifonAttach

ListFragment 的onListItemClick 方法中调用了哪个onItemSelected 方法,需要实现的方法还是FragmentActivity 中的onItemSelected?

在一个非常原始的解释中:保留对类型对象(表示实现接口的类)RecordingListFragment的引用(mCallbacks字段)。最初,对于这个引用,代码将分配一个默认/空引用(sDummyCallbacks),它不做任何事情(所以不,你不必为它提供一些实现),因为它的onItemSelected是空的,这是为了避免在某些情况下可能(例如,如果您没有为该字段分配某些内容并且您调用它)。当方法运行时,对this存在的地方的引用将被转换为 a并放入CallbacksCallbacksCallabacksCallbackssDummyCallbacksNullPointerExceptionmCallbacksonItemSelectedonAttachActivityFragmentCallbaksmCallbacks场地。发生这种情况后,当您调用'方法时,将调用mCallbacks.onItemSelected()该方法中的代码。如果稍后调用 ,将再次指向,在这种情况下,调用将什么也不做。FragmentActivityonItemSelectedonDetachmCallbackssDummyCallbacksmCallbacks.onItemSelected()

上面的接口系统很重要,因为它将使您RecordingListFragment的代码中的组件更可重用,因为它不会绑定到特定的Activity实现。当用户单击片段列表中的项目时,您将调用引用以运行该onItemSelected对象(在您的情况下为 Activity)的方法。您的片段不知道如何实现接口,甚至不在乎。例如,假设您有三个活动,每个活动都使用一个片段。您需要如何更改类以使其与将要使用的三个活动一起使用?mCallbacksonItemSelectedRecordingListFragmentRecordingListFragment

所有这些 onItemSelected 方法都采用 String 类型的 id(因为 DummyContent id 是一个字符串)。如果我将 DummyContent id 更改为 long,我需要更改哪些 onItemSelected 方法?我尝试更改 FragmentActivity 中的那个,但这有 @Override 所以我不允许:(

修改界面:

public interface Callbacks {

        public void onItemSelected(long id);
}

如果你保存 java 文件,Eclipse 会抱怨(你必须重写一个超类方法)这个接口是在哪里实现的。对于sDummyCallbacks

private static Callbacks sDummyCallbacks = new Callbacks() {
    @Override
    // NEEDS IMPLEMENTATION - i guess???? <- it doesn't need no implementation
    // it's purpose is to do nothing
    public void onItemSelected(long id) {
    }
};

FragmentActivity实现了Callbacks接口,因此您也需要更改它:

public class RecordingListActivity extends FragmentActivity
        implements RecordingListFragment.Callbacks {

    @Override
    public void onItemSelected(long id) {
        if (mTwoPane) {
    // ...

最后你会mCallbacks在你的片段中使用:

@Override
public void onListItemClick(ListView listView, View view, int position, long id) {     
    mCallbacks.onItemSelected(id);
}

我建议您花一些时间来学习一下 java 语言,这样您将努力理解 Android 代码,而不是 Android 代码 + java 方式。

于 2012-11-26T07:54:48.297 回答