强制选项卡内容在异步任务完成后更新

时间:2011-06-02 19:09:44

标签: java android refresh tabactivity

我有TabActivity个标签。有一个异步任务,当通过单击菜单项进行刷新运行时,从服务器检索更新的数据。此数据存储在控制器中,并由所有视图访问,因此模型只需加载一次。

我的问题是,在运行异步活动并更新模型后,如何通知所有三个标签以更新其内容?

我的活动

public class DashboardActivity extends TabActivity {
    private ProfileModel profile;
    private TabHost tabHost;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        profile = Controller.getProfile();

        this.setContentView(R.layout.dashboard);

        tabHost = getTabHost();
        setupTab(new TextView(this), "Home", new Intent().setClass(DashboardActivity.this, HomeActivity.class));
        setupTab(new TextView(this), "History", new Intent().setClass(DashboardActivity.this, PaymentsActivity.class));
        setupTab(new TextView(this), "My Wallet", new Intent().setClass(DashboardActivity.this, MyWalletActivity.class));

        tabHost.setCurrentTab(0);

        ActionBar actionBar = (ActionBar)findViewById(R.id.actionbar);
        actionBar.setTitle(profile.Name);

    }

    private void setupTab(final View view, final String tag, Intent content) {
        View tabview = createTabView(tabHost.getContext(), tag);
            TabSpec setContent = tabHost.newTabSpec(tag)
                .setIndicator(tabview)
                .setContent(content);
            tabHost.addTab(setContent);
    }

    private static View createTabView(final Context context, final String text) {
        View view = LayoutInflater.from(context).inflate(R.layout.tabs_bg, null);
        TextView tv = (TextView) view.findViewById(R.id.tabsText);
        tv.setText(text);
        return view;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.mainmenu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
        case R.id.menu_settings:

            return true;
        case R.id.menu_refresh:
            new RefreshDashboardTask().execute();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }


    private class RefreshDashboardTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected void onPreExecute()
        {
            ActionBar actionBar = (ActionBar)findViewById(R.id.actionbar);

            if(actionBar != null)
                actionBar.setProgressBarVisibility(View.VISIBLE);
        }

        @Override
        protected Void doInBackground(Void... params) 
        {
            try {
                profile = DataHelper.getProfile();
                Controller.setProfile(profile);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (HttpException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ServerException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(Void result)
        {
            ActionBar actionBar = (ActionBar)findViewById(R.id.actionbar);

            if(actionBar != null)
                actionBar.setProgressBarVisibility(View.GONE);
        }
    }
}

编辑为了进一步详细说明,这里还有一些代码。

我的控制器

public class Controller extends Application {
    private static Controller instance;
    private static DefaultHttpClient client;
    private static ProfileModel profile;

    public Controller() {
        instance = this;
        client = new DefaultHttpClient();
        profile = null;
    }

    public static Context getContext() {
        return instance;
    }

    public static DefaultHttpClient getHttpContext() {
        return client;
    }

    public static ProfileModel getProfile() {
        return profile;
    }

    public static void setProfile(ProfileModel profile) {
        Controller.profile = profile;
    }

    @Override
    public void onCreate() 
    {
        super.onCreate();

    }
}

我在标签视图中的一项活动。这个是最简单的一个,因为它只是一个列表。主视图是2个列表,由标题分隔,钱包视图是动态生成的列表,带有标题,从集合中的集合创建。

public class PaymentsActivity extends Activity {
    ProfileModel profile;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.setContentView(R.layout.payment_history);

        profile = Controller.getProfile();

        ListView itemList = (ListView)this.findViewById(R.id.payment_history_list);
        itemList.setTextFilterEnabled(true);
        itemList.clearChoices();
        itemList.setAdapter(new ItemSummaryAdapter(PaymentsActivity.this, R.layout.list_item_payment, profile.Items));
        //statementList.setOnItemClickListener(clickListener);
    }
}

此处的目标是刷新按钮更新控制器中的数据。选项卡内的所有视图都会更新。

2 个答案:

答案 0 :(得分:3)

更新:

如果我是你,我会Observer pattern。首先,向Controller类添加一组侦听器:

public class Controller extends Application {
    private static Controller instance;
    private static DefaultHttpClient client;
    private static ProfileModel profile;
    private static Set<ControllerUpdateListener> updateListeners = new HashSet<ControllerUpdateListener>();

    //...

    public static void addListener(ControllerUpdateListener listener)
    {
        updateListeners.add(listener);
    }

    public static interface ControllerUpdateListener {
        void onControllerUpdate(ProfileModel model);
    }
}

然后让您的各个标签活动实施ControllerUpdateListener。最后,将触发器添加到Controller类:

public static void setProfile(ProfileModel profile) {
    Controller.profile = profile;

    for(ControllerUpdateListener l : updateListeners) {
        l.onControllerUpdate(profile);
    }
}

不要忘记将每个活动注册为Controller

的监听器
public class PaymentsActivity extends Activity implements Controller.ControllerUpdateListener {
    ProfileModel profile;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.setContentView(R.layout.payment_history);

        Controller.addListener(this); // <-- Don't forget this...
        profile = Controller.getProfile();

        ListView itemList = (ListView)this.findViewById(R.id.payment_history_list);
        itemList.setTextFilterEnabled(true);
        itemList.clearChoices();
        itemList.setAdapter(new ItemSummaryAdapter(PaymentsActivity.this, R.layout.list_item_payment, profile.Items));
        //statementList.setOnItemClickListener(clickListener);
    }

    public void onControllerUpdate(ProfileModel model) {
        //update these views...
    }
}

现在,您的每个标签活动都应在notifyDataSetChanged()方法中触发onControllerUpdate(ProfileModel)(或其他任何触发更新的方法)。

答案 1 :(得分:2)

在刷新视图中的内容后,是否在适配器上调用notifyDataSetChanged()?如果它是一个ListView,那么只是通知适配器应该触发刷新。这实际上是你应该处理ListView中的行的唯一方法。