刷新片段内的视图

时间:2012-10-03 09:15:42

标签: java android android-fragments android-view android-loadermanager

我搜索了很多看起来像这样的问题,但是没有找到我的答案。

我有一个活动,可以通过操作栏访问3个标签。我通过添加3个片段来实现这一点,这些片段会扩展我扩展视图类的自定义视图。

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

然而,当我转到另一个标签然后返回时,已经进行了更改并且我的视图已按原样更新。

如何模拟更改为另一个标签时发生的相同事情?会发生什么我试着看看片段生命周期(试图调用onCreateView())来解决它,但它只是不想刷新/重绘它。

正确加载数据,因为当我更改为另一个标签时数据会发生变化。

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

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

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) {
}
}

5 个答案:

答案 0 :(得分:21)

  1. 不要试图自己调用onCreateView() ......这是一种生命周期方法,只能由框架调用。

  2. Fragment是可重复使用的UI组件。他们有自己的生命周期,显示自己的视图,并定义自己的行为。您通常不需要Activity使用Fragment的内部工作,因为Fragment的行为应该是自包含的并且独立于任何特定的Activity Fragment。 1}}。

    尽管如此,我认为最好的解决方案是让每个LoaderManager.LoaderCallbacks<D>实现Fragment接口。如果您使用的是由SQLite数据库支持的Loader,则每个CursorLoader都会初始化ContentProvider(即LoaderonLoadFinished()将负责(1)在后台线程上加载数据,以及(2)监听对数据源进行的内容更改,并在发生内容更改时将新数据传递给onLoadFinished()

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

  3. 如果你很懒,只想要一个快速的解决方案,你也可以通过onResume()的{​​{1}}方法刷新视图。

    < / LI>

答案 1 :(得分:4)

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

在我添加的片段中

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

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

答案 2 :(得分:3)

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

虽然我的问题实际上没有解决,但我还是给了Alex Lockwood奖励。他对装载机的建议使我的应用更好,这让我一直在寻找我最终找到的解决方案。

答案 3 :(得分: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;

答案 4 :(得分:2)

为我工作的最快解决方案:

 @Override
    public void onPause() {
        super.onPause();
        if (isRemoving() && fragmentView != null) {
            ((ViewGroup) fragmentView).removeAllViews();
        }
    }