【问题标题】:AsyncTask is re-executing while switching between fragmentsAsyncTask 在片段之间切换时重新执行
【发布时间】:2014-07-16 07:25:05
【问题描述】:

我有一个从 Activity 扩展而来的 MainActivity.class。我创建了一个类似结构的标签。单击任何图像。显示新片段。我的第一个片段是Article。它有一个 AsyncTask 与之关联。

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

我在添加片段时有addToBackStack(null);

getFragmentManager().beginTransaction().replace(R.id.container, new Article()).addToBackStack(null).commit();

Article 是 fragment,容器是 mainActivity.xml 中的 frameLayout

我想显示我离开的片段。就像我们在活动中所做的那样,通过设置 LaunchMode+"Single" 或其他东西。我没有清除 backStack。

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

文章片段

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

MainActivity

public class MainActivity extends Activity //implements FragmentDelegate,FragmentManager.OnBackStackChangedListener
{
    public LinearLayout Tab1,Tab2,Tab3,Tab4;

    public ImageView img1,img2,img3,img4;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.practicing);

        init();
    }

    private void init()
    {
        Tab1 = (LinearLayout) findViewById(R.id.tab1);

        Tab2 = (LinearLayout) findViewById(R.id.tab2);

        Tab3 = (LinearLayout) findViewById(R.id.tab3);

        Tab4 = (LinearLayout) findViewById(R.id.tab4);

        img1 = (ImageView)findViewById(R.id.tab_img1);

        img2 = (ImageView)findViewById(R.id.tab_img2);

        img3 = (ImageView)findViewById(R.id.tab_img3);

        img4 = (ImageView)findViewById(R.id.tab_img4); 

        getFragmentManager().beginTransaction().replace(R.id.container, new Article()).addToBackStack(null).commit();   
    }

    public void selectFrag(View view) {

        Fragment fr = null;

        if (view == findViewById(R.id.tab1)) 
        {           
            img1.setBackgroundResource(R.drawable.articles_on);

            img2.setBackgroundResource(R.drawable.forum_off);

            img3.setBackgroundResource(R.drawable.video_off);

            img4.setBackgroundResource(R.drawable.profile_off);

            fr = new Article();
        } 
        else if(view == findViewById(R.id.tab2)) 
        {
            img1.setBackgroundResource(R.drawable.articles_off);

            img2.setBackgroundResource(R.drawable.forum_on);

            img3.setBackgroundResource(R.drawable.video_off);

            img4.setBackgroundResource(R.drawable.profile_off);

            fr = new Forum();
        }
        else if(view == findViewById(R.id.tab3))
        {
            img1.setBackgroundResource(R.drawable.articles_off);

            img2.setBackgroundResource(R.drawable.forum_off);

            img3.setBackgroundResource(R.drawable.video_on);

            img4.setBackgroundResource(R.drawable.profile_off);

            fr = new Medias();
        }
        else if(view == findViewById(R.id.tab4))
        {
            img1.setBackgroundResource(R.drawable.articles_off);

            img2.setBackgroundResource(R.drawable.forum_off);

            img3.setBackgroundResource(R.drawable.video_off);

            img4.setBackgroundResource(R.drawable.profile_on);

            fr = new Profile();
        }

        FragmentManager fm = getFragmentManager();

        FragmentTransaction fragmentTransaction = fm.beginTransaction();

        fragmentTransaction.replace(R.id.container, fr);

        fragmentTransaction.addToBackStack(null);//MainActivity.TAG);//.addToBackStack(null);

        fragmentTransaction.commit();


    }
}

practicing.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/bottom" />

    <LinearLayout
        android:id="@+id/bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:baselineAligned="false"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal" >

        <LinearLayout
            android:id="@+id/tab1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:onClick="selectFrag"
            android:gravity="center"
            android:orientation="vertical" >

            <ImageView
                android:id="@+id/tab_img1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"
                android:background="@drawable/articles_on"
                android:padding="10dp"
                android:scaleType="center" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/tab2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:onClick="selectFrag"
            android:gravity="center"
            android:orientation="vertical" >

            <ImageView
                 android:id="@+id/tab_img2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"
                android:background="@drawable/forum_off"
                android:padding="10dp"
                android:scaleType="center" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/tab3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:onClick="selectFrag"
            android:gravity="center"
            android:orientation="vertical" >

            <ImageView
                 android:id="@+id/tab_img3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"
                android:background="@drawable/video_off"
                android:padding="10dp"
                android:scaleType="fitXY" />


        </LinearLayout>

        <LinearLayout
            android:id="@+id/tab4"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:onClick="selectFrag"
            android:gravity="center"
            android:orientation="vertical" >

            <ImageView
                 android:id="@+id/tab_img4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"
                android:background="@drawable/profile_off"
                android:padding="10dp"
                android:scaleType="fitXY" />


        </LinearLayout>
    </LinearLayout>

</RelativeLayout>

【问题讨论】:

    标签: android android-asynctask fragment


    【解决方案1】:

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

    【讨论】:

    • 在片段生命周期中添加或替换片段有什么区别
    • 使用replace本质上与调用remove(Fragment)对所有当前使用相同containerViewId添加的fragment然后add(int, Fragment, String)调用相同。
    • 仍在相互调用和添加所有其他片段
    • 尝试隐藏您当前的片段。这将使您当前的视图保持不变。
    • 我使用 add 而不是 replace 但 asyncTask 在切换时再次调用
    【解决方案2】:

    addToBackStack() 所做的是:它将片段 transaction 添加到它的堆栈中,因此它知道当您按下返回时,它应该显示您的第一个片段。所以 t 正是这样做的,并再次显示您的第一个片段,并且片段的 onCreatView()再次调用。在您的 onCreateView 中,所有初始化都会发生并调用 AsyncTask。这就是为什么每次在片段之间更改时都会发生这种情况。

    我针对这个问题实现的解决方案是:

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

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

    【讨论】:

    • 请展示一些代码。以及如何将片段视图保留为类变量。以及您的代码中的视图是什么
    • @Nepster 查看已编辑的答案,现在是您的代码。
    • 我也添加了我的 MainActivity 及其 xml。你的回答没有用。看看我是不是弄错了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-10
    • 1970-01-01
    • 2012-01-07
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多