3

私はTabActivity3つのタブを持っています。更新用のメニュー項目をクリックして実行すると、更新されたデータをサーバーから取得する非同期タスクがあります。このデータはコントローラに格納され、すべてのビューからアクセスされるため、モデルを一度ロードするだけで済みます。

私の問題は、非同期アクティビティが実行されてモデルが更新された後、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);
        }
    }
}

EDITさらに詳しく説明するために、さらにコードを示します。

私のコントローラー

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();

    }
}

そして、タブビュー内にある私の活動の1つ。これは単一のリストであるため、最も単純なものです。ホーム ビューは、ヘッダーで区切られた 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);
    }
}

ここでの目標は、更新ボタンでコントローラーのデータを更新することです。タブ内のすべてのビューが更新されます。

4

2 に答える 2

3

更新しました:

もし私があなたなら、オブザーバーパターンになります。まず、一連のリスナーを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)

于 2011-06-02T19:25:51.840 に答える
2

ビューのコンテンツを更新した後、アダプターで notifyDataSetChanged() を呼び出していますか? ListView の場合は、アダプターに通知するだけで更新がトリガーされます。実際、これは ListView 内で行を処理する唯一の方法です。

于 2011-06-02T19:50:44.990 に答える