2

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

这是片段的代码:

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;   
}       
}

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

这是片段容器活动:

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()但应用程序强制关闭,说明 FragmentTransaction 不能添加到后台堆栈。我过去也尝试过离线缓存图像,为了避免数据消耗,应用程序仍然需要从本地 URI 解析图像并使用处理能力。

我可以尝试任何想法吗?

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

4

2 回答 2

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() 来恢复它。非常简单,我从来没有想过。

于 2012-11-05T04:10:40.303 回答
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);
    }

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

于 2012-10-04T08:56:12.967 回答