异步任务完成后强制更新选项卡内容
我有一个带有 3 个选项卡的 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);
}
}
这里的目标是刷新按钮更新控制器中的数据。我在选项卡中的所有视图都已更新。
I have a TabActivity
with 3 tabs. There is an async task that when run by clicking a menu item for refresh, retrieves updated data from the server. This data is stored in the controller and is accessed by all views, so that the model only needs to be loaded once.
My problem is that after the async activity runs and the model is updated, how do I signal all three tabs to update their content?
My activity
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);
}
}
}
EDIT For further elaboration, here is some more code.
My controller
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();
}
}
And one of my activities that is inside the tab view. This one is the simplest one, as it is just a single list. The home view is 2 lists, separated by headers, and the wallet view is dynamically generated lists with headers, created from a collection within a collection.
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);
}
}
The goal here is that the refresh button updates the data in the controller. All my views inside the tabs are updated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
更新:
如果我是你,我会使用观察者模式。首先,向您的 Controller 类添加一组侦听器:
然后让您的各个选项卡活动实现
ControllerUpdateListener
。最后,将触发器添加到Controller
类中:不要忘记将每个活动注册为
Controller
的侦听器:现在,每个单独的选项卡活动都应该触发其 <
onControllerUpdate(ProfileModel)
方法中的 code>notifyDataSetChanged() (或触发其更新的任何其他方法)。UPDATED:
If I were you I would the Observer pattern. First, add a set of listeners to your Controller class:
Then have your individual tab activities implement
ControllerUpdateListener
. Finally, add the trigger to theController
class:Don't forget to register each activity as a Listener with the
Controller
:Now each of your individual tab activities should trigger their
notifyDataSetChanged()
(or whatever other method triggers their update) in theonControllerUpdate(ProfileModel)
method.刷新视图中的内容后,您是否在适配器上调用notifyDataSetChanged()?如果它是 ListView,那么只需通知适配器就应该触发刷新。事实上,这是处理 ListView 中的行的唯一方法。
Are you calling notifyDataSetChanged() on your adapter after refreshing the content in your views? If its a ListView then just notifying the adapter should trigger a refresh. This in fact is the only way you should be dealing with rows inside ListView.