1

ListViewの内部をリロードしようとして立ち往生していListFragmentます。リフレッシュは、 で作成したリスナーを介して呼び出されFragmentDialogます。reloadItemsメソッドが適切に呼び出され、アイテムのリストが変数で正しく更新されていることを確認しました

これは簡単なことのように思えますが、行き詰まっています。ListView が実際に更新されることはありませんが、Context使用済みに関係していると思います。

onClickListViewプロパティを使用して設定された行のボタンを介して呼び出されandroid:onClickます。

ソリューション 問題は、作成中にタブ アダプタgetItem(...)が予期せず再度呼び出されたAlertDialogことでした。コードが貧弱だったため、タブが再インスタンス化され、表示されているフラグメントで更新が行われませんでした。(最後に元のコードを参照してください)

これが発見されたら(受け入れられた回答を参照)、コードタブアダプターを作り直して参照を維持することで修正できました。ViewPager誰にとっても役立つ場合に備えて、これが私の作業中のタブアダプターです。

public class TabsAdapter extends FragmentPagerAdapter implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
    private final Context mContext;
    private final ActionBar mActionBar;
    private final ViewPager mViewPager;
    private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
    private ArrayList<Fragment> mFragments = new ArrayList<Fragment>();

    static final class TabInfo {
        private final Class<?> mClass;
        private final Bundle mArgs;

        TabInfo(Class<?> _class, Bundle _args) {
            mClass = _class;
            mArgs = _args;
        }

        public String getClassName() {
            return mClass.getName();
        }

        public Bundle getArgs() {
            return mArgs;
        }
    }

    public TabsAdapter(Activity activity, ViewPager pager) {
        super(activity.getFragmentManager());
        mContext = activity;
        mActionBar = activity.getActionBar();
        mViewPager = pager;
        mViewPager.setAdapter(this);
        mViewPager.setOnPageChangeListener(this);
    }

    public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
        TabInfo info = new TabInfo(clss, args);
        tab.setTag(info);
        tab.setTabListener(this);
        mTabs.add(info);
        mActionBar.addTab(tab);
        Fragment fragment = Fragment.instantiate(mContext, info.getClassName(), info.getArgs());
        mFragments.add(fragment);

        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return mTabs.size();
    }

    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }

    public void onPageSelected(int position) {
        mActionBar.setSelectedNavigationItem(position);
    }

    public void onPageScrollStateChanged(int state) {
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        Object tag = tab.getTag();
        for (int i = 0; i < mTabs.size(); i++) {
            if (mTabs.get(i) == tag) {
                mViewPager.setCurrentItem(i);
            }
        }
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }
}

ソリューションの終了

アクティビティ

public class MyActivity extends Activity {
    // unrelated code removed

    public void onClick(View v) {
        // onClick is called via a button on a list item
        MyFragment sf = (MyFragment)mTabsAdapter.getItem(0);
        sf.myClick(v, getFragmentManager());
    }
}

マイフラグメント

public class MyFragment extends ListFragment {

    static final String TAG = "StatusFragment";
    private ArrayList<MyObject> mItems = null;
    AlarmDataSource datasource;
    StatusAdapter mAdapter;

    public void reloadItems(Context context) {
        Log.d(TAG, "reloadItems");

        datasource = new MyObjectDataSource(context);
        datasource.open();

        mItems = new ArrayList<MyObject>();
        ArrayList<MyObject> active = (ArrayList<MyObject>)datasource.getAllEnabled();
        for (int i = 0; i < active.size(); i++) {
            MyObject next = active.get(i);
            mItems.add(next);
        }

        mAdapter = new StatusAdapter(
                context,
                R.layout.status_list_item,
                mItems);

        // set a breakpoint and this is called when called from
        // statusOptionDialogClose below. Here mAdapter DOES HAVE updated items
        // inside. However getView within the adaper is NOT called
        setListAdapter(mAdapter);

        datasource.close();
    }

    public void myClick(View v, FragmentManager manager) {
        StatusOptionDialog sod = StatusOptionDialog.newInstance(v.getContext());
        sod.setStatusOptionDialogListener(new StatusOptionDialogListener() {

            public void statusOptionDialogClose(Context context) {
                // this is correctly called when dialog closed
                // context is the same as sent in with newInstance above.
                reloadItems(context);
            }
        });
        sod.show(manager, "StatusOptionDialog");
    }
}

何かおかしなところを見た人はいますか?さまざまな方法を試しましたが、何もうまくいきませんでした。

更新時にも試しましmAdapter.notifyDataSetChanged()たが、どちらも機能しません。今日の後半に Android SDK コードをステップ実行して、データがアダプターに届かない場合や何か奇妙な場合に備えて、そこにあるデータも特定できるかどうかを確認します。

更新問題の詳細を追跡しました。setListItem(mAdapter)アイテムを更新したmAdapterを正常に呼び出した後、アダプターgetView(...)が呼び出されないようです。

更新 #2reloadItems(...)問題のある最も単純なコードに絞り込んだ関数を投稿しました。setListAdapter(...)更新されたアイテムを持つ更新されたアダプターで呼び出されます。ただし、経由でgetView(...) 呼び出されたときに呼び出されることはありませんreloadItems(...)statusOptionDialogClose(...)

アプリケーションを終了して再起動すると、更新されたデータが ListView に表示されます。reloadItems を再度呼び出すと、更新されません。

アダプタ

public class StatusAdapter extends ArrayAdapter<MyObject> {

    private Context mContext;
    private int mRes;
    private ArrayList<MyObject> mItems;

    public StatusAdapter(Context context, int textViewResourceId, ArrayList<MyObject> items) {
        super(context, textViewResourceId, items);
        this.mItems = items;
        this.mRes = textViewResourceId;
        this.mContext = context;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        if (v == null) {
            LayoutInflater vi = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(mRes, null);
        }
        Alarm a = mItems.get(position);
        if (a != null) {
            // fills out list item
        }
        return v;
    }

    @Override
    public int getCount() {
        return mItems.size();
    }

    public void setNewList(ArrayList<Alarm> items) {
        this.mItems = items;
    }
}

タブ アダプタおよび タブを有効にするために使用されViewPagerます。

public class TabsAdapter extends FragmentPagerAdapter implements
        ActionBar.TabListener, ViewPager.OnPageChangeListener {
    private final Context mContext;
    private final ActionBar mActionBar;
    private final ViewPager mViewPager;
    private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();

    static final class TabInfo {
        private final Class<?> clss;
        private final Bundle args;

        TabInfo(Class<?> _class, Bundle _args) {
            clss = _class;
            args = _args;
        }
    }

    public TabsAdapter(Activity activity, ViewPager pager) {
        super(activity.getFragmentManager());
        mContext = activity;
        mActionBar = activity.getActionBar();
        mViewPager = pager;
        mViewPager.setAdapter(this);
        mViewPager.setOnPageChangeListener(this);
    }

    public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
        TabInfo info = new TabInfo(clss, args);
        tab.setTag(info);
        tab.setTabListener(this);
        mTabs.add(info);
        mActionBar.addTab(tab);
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return mTabs.size();
    }

    @Override
    public Fragment getItem(int position) {
        TabInfo info = mTabs.get(position);
        return Fragment.instantiate(mContext, info.clss.getName(), info.args);
    }

    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }

    public void onPageSelected(int position) {
        mActionBar.setSelectedNavigationItem(position);
    }

    public void onPageScrollStateChanged(int state) {
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        Object tag = tab.getTag();
        for (int i = 0; i < mTabs.size(); i++) {
            if (mTabs.get(i) == tag) {
                mViewPager.setCurrentItem(i);
            }
        }
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }
}
4

3 に答える 3

3

毎回アダプタを設定するのではなく、アダプタを更新してください。

mAdapter.setNewList(newList);    //custom method, just replace the old list with the new one
mAdapter.notifyDataSetChanged();

つまりsetListAdapter(mAdapter);、毎回使用する必要はなく、初めて使用する必要があります。

これがお役に立てば幸いです。

于 2012-08-01T14:55:38.443 に答える
1

理論的には(他の人が指摘しているように)呼び出しnotifyDataSetChanged()で十分ですがListView.invalidateViews()、メソッドのデータを更新した後に呼び出すとsetNewList()、リストに新しいデータが表示されるようになるかどうかを確認してください(getView()メソッドを呼び出す必要があります)。

getView()強制したときに呼び出されても古いデータが残っている場合は、何らかの理由でListFragmentの冗長コピーがある可能性があります(そして、更新されたアダプターデータを持つものは表示されません)。mTabsAdapterたぶん、あなたはあなたの実装を調べる必要があるでしょう。

于 2012-08-13T14:27:30.713 に答える
0

CFlexが言ったように、最初に作成されsetListAdapter()たときに1回だけ呼び出す必要がありますFragment

リストをクリアしようとしているようです。通常、Adapter使用するclear()メソッドには、データオブジェクトを毎回完全に再割り当てするよりも少しすっきりする可能性がある、それを処理するメソッドがあります。カスタムを使用している場合はAdapter、メソッドを自分でオーバーライドするだけです。notifyDataSetChanged()データにすべての変更を加えた後は、必ず電話してください。これにより、はListViewビューを更新します。

于 2012-08-01T15:03:53.433 に答える