在通过ActionBar添加的Fragment上调用addToBackStack()

时间:2012-10-04 08:49:32

标签: android android-fragments android-lifecycle

基本上,我有一个简单的Fragment,它使用AsyncTask从URL下载位图,然后在ImageView中显示它。

这是Fragment的代码:

public class TestFragment extends Fragment {

public TestFragment () {}

private String pictureUrl = "https://fbcdn-sphotos-d-a.akamaihd.net/hphotos-ak-prn1/532762_10150739418088211_1186720820_n.jpg";

private TextView sampleText;
private ImageView sampleImage;

public View onCreateView(LayoutInflater inflater, ViewGroup container, 
        Bundle savedInstanceState) {

    View root = inflater.inflate(R.layout.fragment_view, container, false); 
    String textToSet = "Section Three";

    sampleText = (TextView) root.findViewById(R.id.textView1);
    sampleText.setText(textToSet);

    sampleImage = (ImageView) root.findViewById(R.id.imageView1);
    DownloadImageTask task = new DownloadImageTask(pictureUrl, root, sampleImage.getId());
    task.execute();

    return root;   
}       
}

这个相同的片段显示三次,ActionBar中每个标签一个。我遇到的问题是,每次用户选择不同的选项卡时,前一个选项卡都会被销毁,当用户导航回原始选项卡时,内容需要重新加载。我想确保消耗最少量的资源(同时保存数据和有价值的overHead处理)。

这是片段容器活动:

public class LayoutContainer extends Activity{

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_layout_container);      

    if (savedInstanceState != null) {
        return;
    }

    final ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    Tab tab = actionBar.newTab()
            .setText(R.string.title_section1)
            .setTabListener(new TabListener<TestFragment>(
                    this, "one", TestFragment.class));
    actionBar.addTab(tab);

    tab = actionBar.newTab()
            .setText(R.string.title_section2)
            .setTabListener(new TabListener<TestFragment>(
                    this, "two", TestFragment.class));
    actionBar.addTab(tab);

    tab = actionBar.newTab()
            .setText(R.string.title_section3)
            .setTabListener(new TabListener<TestFragment>(
                    this, "three", TestFragment.class));
    actionBar.addTab(tab);

}

public static class TabListener<T extends Fragment> implements ActionBar.TabListener {

    private Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    public TabListener(Activity activity, String tag, Class<T> clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        if (mFragment == null) {
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
        }
        ft.replace(android.R.id.content, mFragment, mTag);
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.addToBackStack(null);
        ft.commit();
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }
}

我目前已将其设置为在 OnTabSelected()方法上调用 ft.replace(),但我之前尝试使用 ft.add() 即可。我在 OnTabUnselected()中的当前 ft.addToBackStack()调用也是如此,我最初将其设置为只需调用 ft.detach()但这就是我所说的同样的问题。它以这种方式加载,但它必须每次都下载图像。

现在,我尝试调用 addToBackStack(),但app force关闭说明FragmentTransaction无法添加到后台堆栈。我也曾尝试过离线缓存图像,以避免数据消耗,应用程序仍然需要从本地URI解析图像并使用处理能力。

我可以尝试任何想法吗?

仅供参考,是的,我知道同一个片段正在所有三个选项卡上加载相同的图像。这仅仅是一个测试项目,旨在帮助我更好地理解Fragments的生命周期。

2 个答案:

答案 0 :(得分:2)

所以在经过大量阅读后,我意识到重要的代码块不是在你的TabListener上完成的,而是在你使用的每个Fragment上完成的。

当离开它时,片段将被分离,但这并不意味着我不能使用onSaveInstanceState(...)保持它状态。

这是在分离后保留Fragment状态所需的简单实现。

public class TimelineFragment extends ListFragment{
...

public TimelineFragment () {}

public void onSaveInstanceState(Bundle outState){
    getActivity().getFragmentManager().putFragment(outState, TAG, this);        
}

public void onRetoreInstanceState(Bundle inState){
    getActivity().getFragmentManager().getFragment(inState, TAG);
}
...
}

我们通过调用putFragment()来保存Fragment,并通过调用getFragment()来恢复它。非常简单,我从未想过它。

答案 1 :(得分:1)

当用户需要网络上的图像时我会做什么我首先检查我是否已将其缓存或图像位于SD。如果在SD或缓存中找不到图像,我下载图像,将其存储到SD并将其添加到缓存中。

它通常是这样的:

    Bitmap cacheBitmap = Database.getImageFromMemory(exercise.image, getActivity());

    if(cacheBitmap != null) {
        image.setImageBitmap(cacheBitmap);
        progressBar.setVisibility(View.GONE);
    }
    Bitmap localBitmap = ImageDownloader.decodeSampledBitmap(exercise.image, width, height, getActivity());

    if(localBitmap != null) {
        image.setImageBitmap(localBitmap);
        progressBar.setVisibility(View.GONE);
        Database.addBitmapToMemoryCache(exercise.image, localBitmap, getActivity());
    } else {
        ImageDownloader imageDownloader = new ImageDownloader(this.getActivity().getApplicationContext(), image, progressBar, width, height);
        imageDownloader.execute(exercise.image);
    }

现在这不是所有代码,但它可以让您了解如何处理它。如果您需要更多代码,请随时询问,但您似乎正走在正确的轨道上。