Принудительно обновлять содержимое вкладки после завершения асинхронной задачи - PullRequest
3 голосов
/ 02 июня 2011

У меня есть TabActivity с 3 вкладками. Существует асинхронная задача, которая при запуске, щелкая элемент меню для обновления, извлекает обновленные данные с сервера. Эти данные хранятся в контроллере и доступны для всех представлений, поэтому модель необходимо загрузить только один раз.

Моя проблема в том, что после выполнения асинхронного действия и обновления модели, как я могу сигнализировать всем трем вкладкам обновить их содержимое?

Моя деятельность

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 ]

3 голосов
/ 02 июня 2011

ОБНОВЛЕНО:

Если бы я был вами, я бы использовал Наблюдатель .Во-первых, добавьте набор слушателей в ваш класс 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).

2 голосов
/ 02 июня 2011

Вы вызываете notifyDataSetChanged () на своем адаптере после обновления содержимого ваших представлений?Если это ListView, то просто уведомление адаптера должно вызвать обновление.Фактически это единственный способ, которым вы должны иметь дело со строками внутри ListView.

...