Android标签:Tabhost一次初始化几个标签?

时间:2012-10-15 09:57:43

标签: android

当我的应用运行并显示带有内部列表视图的标签时,我有一种奇怪的情况。问题是不同选项卡的数据一次加载。但它应该看起来只为当前选项卡加载数据,而不是全部或部分选项卡。为什么会这样?

我的主要活动是标签创建和初始化:     公共类MainActivity扩展了SherlockFragmentActivity {     TabHost mTab​​Host;     ViewPager mViewPager;     TabsAdapter mTab​​sAdapter;     Bundle excercises,stretching,warmUp,lowerBody;

@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.Theme_Sherlock); // Used for theme switching in samples
super.onCreate(savedInstanceState);

setContentView(R.layout.home);
mTabHost = (TabHost) findViewById(android.R.id.tabhost);
mTabHost.setup();

mViewPager = (ViewPager) findViewById(R.id.pager);

mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager);

excercises = new Bundle();
excercises.putString("category", "Android Application Development Tutorials");
mTabsAdapter.addTab(mTabHost.newTabSpec("Excercises").setIndicator("Excercises"),   VideoListLoader.VideoListFragment.class, excercises);

    stretching = new Bundle();
    stretching.putString("category", "iPhone Development Tutorials");
mTabsAdapter.addTab(mTabHost.newTabSpec("Stretching").setIndicator("Stretching"), VideoListLoader.VideoListFragment.class, stretching);

    warmUp = new Bundle();
    warmUp.putString("category", "PHP Tutorials Playlist");
mTabsAdapter.addTab(mTabHost.newTabSpec("Warm Up").setIndicator("Warm Up"), VideoListLoader.VideoListFragment.class, warmUp);

    lowerBody = new Bundle();
    lowerBody.putString("category", "Algebra Tutorials Playlist");
mTabsAdapter.addTab(mTabHost.newTabSpec("Lower Body").setIndicator("Lower Body"), VideoListLoader.VideoListFragment.class, lowerBody);

if (savedInstanceState != null) {
    mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));
}
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("tab", mTabHost.getCurrentTabTag());
}

/**
 * This is a helper class that implements the management of tabs and all
 * details of connecting a ViewPager with associated TabHost. It relies on a
 * trick. Normally a tab host has a simple API for supplying a View or
 * Intent that each tab will show. This is not sufficient for switching
 * between pages. So instead we make the content part of the tab host 0dp
 * high (it is not shown) and the TabsAdapter supplies its own dummy view to
 * show as the tab content. It listens to changes in tabs, and takes care of
 * switch to the correct paged in the ViewPager whenever the selected tab
 * changes.
 */
public static class TabsAdapter extends FragmentPagerAdapter implements    TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final TabHost mTabHost;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();

static final class TabInfo {
    private final String tag;
    private final Class<?> clss;
    private final Bundle args;

    TabInfo(String _tag, Class<?> _class, Bundle _args) {
    tag = _tag;
    clss = _class;
    args = _args;
    }
}

static class DummyTabFactory implements TabHost.TabContentFactory {
    private final Context mContext;

    public DummyTabFactory(Context context) {
    mContext = context;
    }

    @Override
    public View createTabContent(String tag) {
    View v = new View(mContext);
    v.setMinimumWidth(0);
    v.setMinimumHeight(0);
    return v;
    }
}

public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) {
    super(activity.getSupportFragmentManager());
    mContext = activity;
    mTabHost = tabHost;
    mViewPager = pager;
    mTabHost.setOnTabChangedListener(this);
    mViewPager.setAdapter(this);
    mViewPager.setOnPageChangeListener(this);
}

public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
    tabSpec.setContent(new DummyTabFactory(mContext));
    String tag = tabSpec.getTag();

    TabInfo info = new TabInfo(tag, clss, args);
    mTabs.add(info);
    mTabHost.addTab(tabSpec);
    notifyDataSetChanged();
}

@Override
public int getCount() {
    return mTabs.size();
}

@Override
public Fragment getItem(int position) {
    TabInfo info = mTabs.get(position);
    return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}

@Override
public void onTabChanged(String tabId) {
    int position = mTabHost.getCurrentTab();
    mViewPager.setCurrentItem(position);
}

@Override
public void onPageScrolled(int position, float positionOffset, int   positionOffsetPixels) {
}

@Override
public void onPageSelected(int position) {
    // Unfortunately when TabHost changes the current tab, it kindly
    // also takes care of putting focus on it when not in touch mode.
    // The jerk.
    // This hack tries to prevent this from pulling focus out of our
    // ViewPager.
    TabWidget widget = mTabHost.getTabWidget();
    int oldFocusability = widget.getDescendantFocusability();
    widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
    mTabHost.setCurrentTab(position);
    widget.setDescendantFocusability(oldFocusability);
}

@Override
public void onPageScrollStateChanged(int state) {
}
}

}

我的VideoListLoader:     公共类VideoListLoader扩展了SherlockFragmentActivity {

private static final String TAG = VideoListLoader.class.getName();
VideoListFragment list;
VideoListAdapter mAdapter;

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

FragmentManager fm = getSupportFragmentManager();

// Create the list fragment and add it as our sole content.
if (fm.findFragmentById(android.R.id.content) == null) {
    list = new VideoListFragment();
    fm.beginTransaction().add(android.R.id.content, list).commit();
}
}

public static class VideoListFragment extends SherlockListFragment implements   LoaderCallbacks<RESTLoader.RESTResponse>, OnItemClickListener, OnScrollListener {

private static final int LOADER_PLAYLIST_SEARCH = 0x1, LOADER_VIDEOS_SEARCH = 0x2;
VideoListAdapter mAdapter;
private static final String ARGS_URI = "net.neilgoodman.android.restloadertutorial.ARGS_URI";
private static final String ARGS_PARAMS = "net.neilgoodman.android.restloadertutorial.ARGS_PARAMS";
private static final String MAX_RESULTS = "30";
private int START_INDEX;
List<VideoEntry> playlists;
private String playlistID, category;

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

    mAdapter = new VideoListAdapter(getSherlockActivity());
    setListAdapter(mAdapter);
    mAdapter.clear();
    setListShown(false);
    getListView().setOnItemClickListener(this);
    getListView().setOnScrollListener(this);

    if (savedInstanceState != null) {
    ParseVideoList pvl = savedInstanceState.getParcelable("list");
    Log.e("Saved item: ", pvl.getArrList().get(2).getTitle());
    playlists = pvl.getArrList();
    mAdapter.setData(playlists);

    if (isResumed()) {
        setListShown(true);
    } else {
        setListShownNoAnimation(true);
    }
    } else {
    Uri playlistSearchUri =   Uri.parse("https://gdata.youtube.com/feeds/api/users/thenewboston/playlists");

    Bundle params = new Bundle();
    params.putString("max-results", "50");
    params.putString("alt", "jsonc");
    params.putString("v", "2");

    Bundle args = new Bundle();
    args.putParcelable(ARGS_URI, playlistSearchUri);
    args.putParcelable(ARGS_PARAMS, params);

    getLoaderManager().initLoader(LOADER_PLAYLIST_SEARCH, args, this);

    }
}

@Override
public void onSaveInstanceState(Bundle outState) {

    ParseVideoList pvl = new ParseVideoList();
    pvl.setArrList(playlists);
    outState.putParcelable("list", pvl);
}

@Override
public Loader<RESTLoader.RESTResponse> onCreateLoader(int id, Bundle args) {
    if (args != null && args.containsKey(ARGS_URI) &&  args.containsKey(ARGS_PARAMS)) {
    Uri action = args.getParcelable(ARGS_URI);
    Bundle params = args.getParcelable(ARGS_PARAMS);

    return new RESTLoader(getSherlockActivity(), RESTLoader.HTTPVerb.GET, action, params);
    }

    return null;
}

@Override
public void onLoadFinished(Loader<RESTLoader.RESTResponse> loader, RESTLoader.RESTResponse data) {
    int code = data.getCode();
    String json = data.getData();

// category = getSherlockActivity()。getIntent()。getExtras()。getString(“category”);         category = getArguments()。get(“category”)。toString();         Log.e(“当前类别:”,类别);         Log.e(“JSON:”,json);         switch(loader.getId()){         案例LOADER_PLAYLIST_SEARCH:         if(code == 200&amp;&amp;!json.equals(“”)){

        if (playlistID == null) {
        playlistID = getPlaylistID(getSherlockActivity(), category, json);
        }

        if (playlistID != null) {
        Uri videoSearchUri = Uri.parse("https://gdata.youtube.com/feeds/api/playlists/" + playlistID);

        Bundle params = new Bundle();
        params.putString("max-results", MAX_RESULTS);
        params.putString("start-index", "1");
        params.putString("alt", "jsonc");
        params.putString("v", "2");

        Bundle args = new Bundle();
        args.putParcelable(ARGS_URI, videoSearchUri);
        args.putParcelable(ARGS_PARAMS, params);

        getLoaderManager().initLoader(LOADER_VIDEOS_SEARCH, args, this);
        break;
        } else {
        Toast.makeText(getSherlockActivity(), "No such a playlist", Toast.LENGTH_SHORT);
        }
    }
    break;
    case LOADER_VIDEOS_SEARCH:
    if (code == 200 && !json.equals("")) {

        playlists = getVideoList(getSherlockActivity(), json);
        mAdapter.setData(playlists);

        if (isResumed()) {
        setListShown(true);
        } else {
        setListShownNoAnimation(true);
        }

    } else {
        Toast.makeText(getSherlockActivity(), "Failed to load data. Check your internet settings.", Toast.LENGTH_SHORT).show();
    }
    break;
    }
}

@Override
public void onLoaderReset(Loader<RESTLoader.RESTResponse> loader) {
    mAdapter.setData(null);

}

private static String getPlaylistID(FragmentActivity fragmentActivity, String pCategory, String json) {
    final Context context = fragmentActivity;
    String playlistID = null;

    try {
    JSONObject playlistsWrapper = (JSONObject) new JSONTokener(json).nextValue();
    JSONArray playlists = playlistsWrapper.getJSONObject("data").getJSONArray("items");

    for (int i = 0; i < playlists.length(); i++) {
        JSONObject playlist = playlists.getJSONObject(i);
        if (pCategory.compareToIgnoreCase(playlist.getString("title")) == 0) {
        VideoEntry entry = new VideoEntry(playlist);
        entry.wrapPlaylistID(context);
        entry.wrapPlaylistTitle(context);
        playlistID = entry.getPlaylistID();
        break;
        }
    }
    } catch (JSONException e) {
    Log.e(TAG, "Failed to parse JSON.", e);
    }

    return playlistID;
}

private static List<VideoEntry> getVideoList(FragmentActivity fragmentActivity, String json) {

    List<VideoEntry> playlistsList = new ArrayList<VideoEntry>();
    final Context context = fragmentActivity;

    try {
    JSONObject playlistsWrapper = (JSONObject) new JSONTokener(json).nextValue();
    JSONArray playlists = playlistsWrapper.getJSONObject("data").getJSONArray("items");
    for (int i = 0; i < playlists.length(); i++) {
        JSONObject playlist = playlists.getJSONObject(i);
        VideoEntry entry = new VideoEntry(playlist);
        entry.wrapID(context);
        entry.wrapTitle(context);
        entry.wrapThumbURL(context);
        playlistsList.add(entry);
        Log.e("PlaylistsList: ", playlistsList.get(i).getThumbURL());
    }
    } catch (JSONException e) {
    Log.e(TAG, "Failed to parse JSON.", e);
    }

    return playlistsList;
}

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    // TODO Auto-generated method stub

    int last_pos = view.getLastVisiblePosition() + 10;
    Log.e("Last_pos in onScroll: ", Integer.toString(last_pos));
    if (last_pos == mAdapter.getCount() && last_pos >= Integer.valueOf(MAX_RESULTS)) {
    START_INDEX = last_pos + 1;
    Log.e("PID in onScroll:", playlistID);
    Log.e("START_INDEX in onScroll:", Integer.toString(START_INDEX));

    Uri videoSearchUri = Uri.parse("https://gdata.youtube.com/feeds/api/playlists/" + playlistID);

    Bundle params = new Bundle();
    params.putString("max-results", MAX_RESULTS);
    params.putString("start-index", Integer.toString(START_INDEX));
    params.putString("alt", "jsonc");
    params.putString("v", "2");

    Bundle args = new Bundle();
    args.putParcelable(ARGS_URI, videoSearchUri);
    args.putParcelable(ARGS_PARAMS, params);

    getLoaderManager().restartLoader(LOADER_VIDEOS_SEARCH, args, this);
    }
}

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
    // TODO Auto-generated method stub

}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    // Intent lVideoIntent = new Intent(null, Uri.parse("ytv://" +
    // mAdapter.getItem(position).getVideoID()), getSherlockActivity(),
    // OpenYouTubePlayerActivity.class);
    // startActivity(lVideoIntent);
    new VideoManager().DownloadFromUrl("https://www.dropbox.com/s/4ph6ibvqn3e5wzq/movie.mp4", "movie.mp4");
}
}

}

我的日志:

10-15 12:39:38.668: E/Current Category:(2397): Android Application Development       Tutorials
10-15 12:39:38.673: E/JSON:(2397): {"apiVersion":"2.1","data":{"totalItems":54,"startIndex":1,"itemsPerPage":50,"items":blablabla ...........

10-15 12:39:39.873: E/Current Category:(2397): Android Application Development Tutorials
10-15 12:39:39.873: E/JSON:(2397): {"apiVersion":"2.1","data":{"id":"PL2F07DBCDCC01493A","author":"thenewboston","title":"blablabla ............

10-15 12:39:41.003: E/Current Category:(2397): iPhone Development Tutorials
10-15 12:39:41.008: E/JSON:(2397): {"apiVersion":"2.1","data":{"totalItems":54,"startIndex":1,"itemsPerPage":50,"items":[{"id":blalblabla ...................

10-15 12:39:42.243: E/Current Category:(2397): iPhone Development Tutorials
10-15 12:39:42.243: E/JSON:(2397): {"apiVersion":"2.1","data":  {"id":"PL53038489615793F7","author":"thenewboston","title":"iPhone Development Tutorials","blalbla ..........

在这里你可以看到2个选项卡的加载数据,但我没有切换到另一个选项卡,只有在第一个选项卡加载必要但是加载一个和第二个选项卡时才会等待。有人可以解释一下为什么会发生这种情况以及如何避免它?

2 个答案:

答案 0 :(得分:0)

默认情况下,ViewPager会将当前页面加载到左侧和右侧。这样做可以让您顺利地滑动页面。

如果您不希望发生这种情况,则不应使用ViewPager(或覆盖其功能)。如果您确实想使用ViewPager,可以将片段逻辑放在onPageSelected()中,或者在父活动中执行逻辑。最后一个选项可能是最好的。

此外,

  

请注意,此课程目前正在进行早期设计和开发。该   API可能会在以后的兼容性库更新中发生变化,   在编译时需要更改应用程序的源代码   反对较新的版本。

我自己的示例代码存在一些问题。

答案 1 :(得分:0)

首先,为了调用mTabHost.setCurrentTabByTag(YOUR_TAG),你切换的每个标签之间必定有一定的延迟。但这不是一个好习惯,任何人都有更好的主意吗?