Android 在片段之间切换时,正在重新执行AsyncTask

Android 在片段之间切换时,正在重新执行AsyncTask,android,android-asynctask,fragment,Android,Android Asynctask,Fragment,我有一个MainActivity.class,它从Activity扩展而来。我创建了一个选项卡式结构。单击任何图像。显示新片段。我的第一个片段是文章。它有一个与之关联的AsyncTask 当我转到另一个片段并返回到它时。请再次调用asyncTask。然后重新创建整个listView。我只是想禁用AsyncTask以便再次调用,并保存片段的先前状态 我有addToBackStacknull;在添加片段时 getFragmentManager().beginTransaction().replace

我有一个MainActivity.class,它从Activity扩展而来。我创建了一个选项卡式结构。单击任何图像。显示新片段。我的第一个片段是文章。它有一个与之关联的AsyncTask

当我转到另一个片段并返回到它时。请再次调用asyncTask。然后重新创建整个listView。我只是想禁用AsyncTask以便再次调用,并保存片段的先前状态

我有addToBackStacknull;在添加片段时

getFragmentManager().beginTransaction().replace(R.id.container, new Article()).addToBackStack(null).commit();
其中,Article是一个片段,container是mainActivity.xml中的frameLayout

我想展示一下我停下来的片段。就像我们在活动中通过设置LaunchMode+Single或其他方式所做的那样。我不是在清理后台

我只需要像在TabActivity中一样在活动之间切换。在TabActivity中,如果要重复AsyncTask,必须在onResume中指定它。否则它将不会被调用

文章片段

而practicing.xml是


尝试添加您的片段而不是替换。

addToBackStack所做的是:它将片段事务添加到其堆栈中,这样它就知道当您按back键时,它应该显示您的第一个片段。所以t确实这样做了,并且再次显示了您的第一个片段,并且再次调用了片段的onCreatView。在onCreateView中,所有初始化都会发生,并调用AsyncTask。这就是为什么每次在片段之间更改时都会发生这种情况

getFragmentManager().beginTransaction().replace(R.id.container, new Article()).addToBackStack(null).commit();
我为这个问题实施的解决方案是:

1) Keep view of fragment as a class variable.
2) Perform all actions in onCreateView() only if the view is null.
所以你应该改变:

public class Article extends Fragment
{
    ListView listView;

    Activity context;

    ArrayList<HashMap<String,String>> art_list;

    ArticleAdapter adapter;

    String url="http://tabletennisdaily.co.uk/webservices/view_articles.php";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState)
    {
        View V = inflater.inflate(R.layout.article, container, false);

        context = getActivity();

        listView = (ListView) V.findViewById(R.id.art_listview);

        new ArticleTask(getActivity(), url, listView).execute(url);

        return V;
    }
}
致:


在这里,我们将视图V移到外部,并使其成为类变量。因此,如果是第一次调用该片段,那么它将为null并进行初始化,否则将转到else black。Else块是必需的,因为onCreateView会添加它作为视图父级的子级返回的任何内容,所以既然V已经存在,我们删除它,然后onCreateView会自动再次添加它。

在片段生命周期中添加或替换片段时有什么区别使用replace本质上与为所有当前添加的片段调用removeFragment相同,这些片段是使用相同的ContainerWebId添加的,然后是addint,fragment,仍在调用并添加所有其他片段,请尝试隐藏当前片段。这将保持当前视图的完整性。我使用add而不是replace,但在切换时再次使用asyncTask调用请显示一些代码。我怎样才能把fragment的视图保持为类变量呢。你的观点是什么code@Nepster请参阅编辑后的答案,现在它与您的代码在一起。我已经添加了我的MainActivity及其xml。你的回答不起作用。看看我是否犯了他们的错误
1) Keep view of fragment as a class variable.
2) Perform all actions in onCreateView() only if the view is null.
public class Article extends Fragment
{
    ListView listView;

    Activity context;

    ArrayList<HashMap<String,String>> art_list;

    ArticleAdapter adapter;

    String url="http://tabletennisdaily.co.uk/webservices/view_articles.php";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState)
    {
        View V = inflater.inflate(R.layout.article, container, false);

        context = getActivity();

        listView = (ListView) V.findViewById(R.id.art_listview);

        new ArticleTask(getActivity(), url, listView).execute(url);

        return V;
    }
}
  public class Article extends Fragment
{   
    ListView listView;

    Activity context;

    ArrayList<HashMap<String,String>> art_list;

    ArticleAdapter adapter;

    String url="http://tabletennisdaily.co.uk/webservices/view_articles.php";

    View V; //SET THE FRAGMENTS VIEW AS A CLASS VARIABLE HERE    

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState)
    {   //CHECK IF FRAGMENT IS INSTANTIATED BEFORE. IF IT IS NOT, CREATE NEW VIEW
        if(V == null){ 
            V = inflater.inflate(R.layout.article, container, false);

            context = getActivity();

            listView = (ListView) V.findViewById(R.id.art_listview);

            new ArticleTask(getActivity(), url, listView).execute(url);

        }
        else{ //IF ALREADY INSTANTIATED USE SAME OLD V 
            ((ViewGroup)V.getParent()).removeView(V);
        }

        return V;
    }
}