20

我已经搜索了许多看起来像这样的问题,但没有在其中任何一个中找到我的答案。

我有一个活动,它有 3 个可通过操作栏访问的选项卡。我通过添加 3 个片段来扩展我扩展视图类的自定义视图来实现这一点。

在数据库更改的那一刻,我尝试通过调用 invalidate()/postinvalidate() 来刷新选项卡中的视图,但这不起作用。就像我考虑的许多其他选项一样,调用片段的 onCreateView 也是如此。

但是,当我转到另一个选项卡并返回时,已进行了更改,并且我的视图已按应有的方式更新。

如何模拟更改到另一个选项卡时发生的相同事情?会发生什么。我试图查看 Fragment 生命周期(试图调用 onCreateView())来弄清楚,但它只是不想像它应该的那样刷新/重绘。

数据已正确加载,因为当我更改为另一个选项卡时数据已更改。

我删除了一些代码,因为它不再相关。我实现了 Cursorloaders 而不是我自己的观察者模式来通知更改。这是我现在的主要活动。

问题是如果我想在这些片段中重绘视图,我现在应该怎么做。如果我应用 fragmentObject.getView().invalidate() 它不起作用。我遇到了和以前一样的问题,但是现在我通知数据库更改的观察者已通过加载器正确实现。

public class ArchitectureActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor> {

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

    ActionBar actionbar = getActionBar();
    actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    ActionBar.Tab EditTab = actionbar.newTab().setText("Edit");
    ActionBar.Tab VisualizeTab = actionbar.newTab().setText("Visualize");
    ActionBar.Tab AnalyseTab = actionbar.newTab().setText("Analyse");

    Fragment editFragment = new EditFragment();
    Fragment visualizeFragment = new VisualizeFragment();
    Fragment analyseFragment = new AnalyseFragment();

    EditTab.setTabListener(new MyTabsListener(editFragment));
    VisualizeTab.setTabListener(new MyTabsListener(visualizeFragment));
    AnalyseTab.setTabListener(new MyTabsListener(analyseFragment));

    actionbar.addTab(EditTab);
    actionbar.addTab(VisualizeTab);
    actionbar.addTab(AnalyseTab);

    ArchitectureApplication architectureApplication = (ArchitectureApplication)getApplicationContext();
    architectureApplication.initialize();

    getLoaderManager().initLoader(0, null, this);
    getLoaderManager().initLoader(1, null, this);
}

public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    if (id == 0){
        return new CursorLoader(this, GraphProvider.NODE_URI , null, null, null, null);
    } else if (id == 1){
        return new CursorLoader(this, GraphProvider.ARC_URI , null, null, null, null);
    }
    return null;
}

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    // Reloading of data, actually happens because when switching to another tab the new data shows up fine
    Log.e("Data", "loaded");
}

public void onLoaderReset(Loader<Cursor> loader) {
}
}
4

5 回答 5

23
  1. 不要试图给onCreateView()自己打电话……这是一个生命周期方法,只能由框架调用。

  2. Fragments 是可重用的 UI 组件。他们有自己的生命周期,展示自己的观点,定义自己的行为。您通常不需要Activity弄乱 a 的内部工作Fragment,因为Fragment's 的行为应该是自包含的并且独立于任何特定的Activity.

    也就是说,我认为最好的解决方案是让你Fragment的每个人都实现LoaderManager.LoaderCallbacks<D>接口。每个都Fragment将初始化一个Loader(即,CursorLoader如果您使用ContentProvider由 SQLite 数据库支持的 a),Loader它将负责 (1) 在后台线程上加载数据,以及 (2) 监听对数据源,并onLoadFinished()在发生内容更改时提供新数据。

    此解决方案比您当前的解决方案更好,因为它完全是事件驱动的。您只需要在数据传递到时刷新视图onLoadFinished()(而不是每次单击新选项卡时都必须手动检查数据源是否已更改)。

  3. 如果您很懒惰并且只想快速解决问题,那么您也可以在Fragment'sonResume()方法中刷新视图。

于 2012-10-07T17:21:44.603 回答
4

我有一个类似(虽然不相同)的问题,我可以通过以下方式解决:

在我添加的片段中

public void invalidate() {
    myView.post(new Runnable() {
        @Override
        public void run() {
            myView.invalidate();
        }
    });
}

当我想刷新片段的视图 myView 时,我从活动中调用了这个方法。post() 的使用确保视图仅在准备好绘制时才失效。

于 2014-05-21T22:36:42.617 回答
3

我找到了一种解决方法来刷新我的片段内的视图。每次更新数据库时,我都会重新创建(新的 CustomView)视图。之后我调用 setContentView(CustomView view)。它看起来更像是一个 hack,但它有效,而我尝试过的其他任何方法都没有。

虽然我的问题并没有真正解决,但我还是把奖励给了 Alex Lockwood。他对 Loaders 的建议使我的应用程序变得更好,并促使我继续寻找最终找到的解决方案。

于 2012-10-12T19:15:35.693 回答
2

我遇到过同样的问题。我的解决方案是分离片段并再次附加它。

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        Fragment f = getFragment(action);
        if(forceUpdate)
        {
            fragmentTransaction.detach(f);
            fragmentTransaction.attach(f);
        }
        fragmentTransaction.replace(R.id.mainFragment, f);
        fragmentTransaction.commit();
        currentAction = action;
于 2013-04-30T15:07:13.863 回答
2

对我来说最快的解决方案:

 @Override
    public void onPause() {
        super.onPause();
        if (isRemoving() && fragmentView != null) {
            ((ViewGroup) fragmentView).removeAllViews();
        }
    }
于 2015-07-14T12:56:02.547 回答