How to retain progress bar state while switching the fragments?

戏子无情 提交于 2019-12-24 11:27:33

问题


I have a navigation drawer where these many options are present

  • Image material
  • Video Material
  • Audio Material

We are maintaining separate fragment for each material and every fragment have grid view in which we are populating thumbnail of that material. Once user click on the thumbnail a full material will be downloaded(Using AsyncTask). I am displaying the progress bar over the thumbnail while downloading the full material.

Now here i stuck to a problem that suppose progress bar is showing 20% and i switched the fragment to another and again came back to the same and the downloading progress bar is lost.

I went to a solution to use intent service and broadcast receiver to populate the progress bar but in that case on every added bytes a broadcasting will be done is it a good practice ?


回答1:


The previous answer wasn't good enough, I made up a new one, have a look, it works very well.

The code consists of the Base Class for fragments, Two fragments, Model for holding data for grid elements and Main UI thread.

The base class:

import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.ArrayList;

/**
 * Created by Movsar Bekaev on 20/09/2015.
 */
public class GridFragment extends Fragment {
    static ArrayList<xThumbnail> myInformation;
    static Activity mActivity;
    GAdapter adapter;
    GridView grid;

    enum fragment_names {FR1, FR2}

    static fragment_names this_fragment_name;

    public GridFragment() {
        refresh();
    }

    protected void refresh() {
        if (grid == null) {
            grid = new GridView(mActivity);
            grid.setLayoutParams(new GridView.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT));
            grid.setBackgroundColor(Color.WHITE);
            grid.setNumColumns(2);
            grid.setColumnWidth(GridView.AUTO_FIT);
            grid.setVerticalSpacing(5);
            grid.setHorizontalSpacing(5);
            grid.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
        }
        adapter = new GAdapter(mActivity, myInformation);
        grid.setAdapter(adapter);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        refresh();
        return grid;
    }


    public class GAdapter extends BaseAdapter {
        private Context mContext;
        private ArrayList<xThumbnail> mInfo;

        // Gets the context so it can be used later
        public GAdapter(Context c, ArrayList<xThumbnail> info) {
            mInfo = info;
            mContext = c;

        }

        // Total number of things contained within the adapter
        public int getCount() {
            return mInfo.size();
        }

        public xThumbnail getItem(int position) {
            return mInfo.get(position);
        }

        // Require for structure, not really used in my code. Can
        // be used to get the id of an item in the adapter for
        // manual control.
        public long getItemId(int position) {
            return position;
        }

        public View getView(final int position,
                            View convertView, ViewGroup parent) {

            View v;
            if (convertView == null) {
                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = inflater.inflate(R.layout.thumbnail, null);
                final TextView tv = (TextView) v.findViewById(R.id.tvClickMe);
                final ProgressBar pb = (ProgressBar) v.findViewById(R.id.prgb_progress);
                pb.setProgress(mInfo.get(position).getProgress());
                tv.setText(mInfo.get(position).getProgress() + "");
                mInfo.get(position).setProgressBar(pb);
                mInfo.get(position).setTextView(tv);
                tv.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        runOp(mInfo.get(position), position, this_fragment_name);
                    }
                });
            } else {
                v = convertView;
            }
            return v;
        }
    }

    private void runOp(final xThumbnail x, final int position, final fragment_names f_name) {
        if (x.xt == null) {
            x.xt = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = x.getProgress(); i <= 100; i++) {

                        //  UNCOMMENT IF YOU WANT TO STOP THE PROCESS AFTER SWITCHING
                        //   if ((f_name == this_fragment_name) && !mThread.isInterrupted()) {
                        final int progress = i;
                        mActivity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                x.setProgressBar(adapter.getItem(position).getProgressBar());
                                x.setTextView(adapter.getItem(position).getTextView());
                                x.setProgress(progress);
                                x.getProgressBar().setProgress(progress);
                                x.getTextView().setText(progress + "");
                                // ARBITRARY CHANGE OF MYINFORMATION
                                // JUST TO SHOW THAT IT WORKS
                                if (progress == 20) {
                                    myInformation.get(3).setProgress(12);
                                    refresh();
                                }
                                // **********************************
                            }
                        });
                        try {
                            Thread.sleep(150);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        //  } else {
                        //       return;
                        //  }
                    }
                }
            });
        }
        if (!x.xt.isAlive())
            x.xt.start();
    }
}

The fr1.java:

 public class fr1 extends GridFragment {
    static ArrayList<xThumbnail> fr1Info;

    public static fr1 newInstance(Activity act) {
        mActivity = act;
        return new fr1();
    }

    @Override
    protected void refresh() {
        if (fr1Info == null || fr1Info.size() == 0) {
            fr1Info = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                xThumbnail x;
                x = new xThumbnail();
                fr1Info.add(x);
            }

        }
        myInformation = fr1Info;
        super.refresh();
    }
}

The fr2.java:

  public class fr2 extends GridFragment {
    static ArrayList<xThumbnail> fr2Info;

    public static fr2 newInstance(Activity act) {
        mActivity = act;
        return new fr2();
    }

    @Override
    protected void refresh() {
        if (fr2Info == null || fr2Info.size() == 0) {
            fr2Info = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                xThumbnail x;
                x = new xThumbnail();
                fr2Info.add(x);
            }
        }
        myInformation = fr2Info;
        super.refresh();
    }
}

The xThumbnail.java (model):

    public class xThumbnail {    
    private int prgb_value = 0;
    private ProgressBar pb;
    private TextView tv;
    public Thread xt;

    public void setProgress(Integer i) {
        prgb_value = i;
    }

    public Integer getProgress() {
        return prgb_value;
    }

    public void setProgressBar(ProgressBar prb) {
        pb = prb;
    }

    public ProgressBar getProgressBar() {
        return pb;
    }

    public void setTextView(TextView tv) {
        this.tv = tv;
    }

    public TextView getTextView() {
        return tv;
    }
}

The MainActivity.java:

 public class MainActivity extends AppCompatActivity {
        Button btn_one, btn_two;
        fr1 mFr1;
        fr2 mFr2;
        FragmentManager fm = getFragmentManager();

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            btn_one = (Button) findViewById(R.id.btn_one);
            btn_two = (Button) findViewById(R.id.btn_two);

            mFr1 = (fr1) fm.findFragmentByTag("fr1");
            mFr2 = (fr2) fm.findFragmentByTag("fr2");
           final FrameLayout frameLayout = (FrameLayout)findViewById(R.id.frLayout);

            btn_one.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

               GridFragment.this_fragment_name= GridFragment.fragment_names.FR1;

                if (mFr1 == null) {
                    mFr1 = fr1.newInstance(MainActivity.this);
                    fm.beginTransaction().add(R.id.frLayout, mFr1, "fr1").commit();
                } else {
                    fm.beginTransaction().detach(mFr1).commit();
                    fm.beginTransaction().attach(mFr1).commit();

                }
            }
        });

        btn_two.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                GridFragment.this_fragment_name= GridFragment.fragment_names.FR2;

                if (mFr2 == null) {
                    mFr2 = fr2.newInstance(MainActivity.this);
                    fm.beginTransaction().add(R.id.frLayout, mFr2, "fr2").commit();
                } else{
                    fm.beginTransaction().detach(mFr2).commit();
                    fm.beginTransaction().attach(mFr2).commit();

                }
            }
        });
        }
    }

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="1"
        android:id="@+id/btn_one"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="2"
        android:id="@+id/btn_two"
        android:layout_alignParentBottom="true"
        android:layout_alignRight="@+id/prgb_uni"
        android:layout_alignEnd="@+id/prgb_uni" />

    <ProgressBar
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/prgb_uni"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="40dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" />

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:id="@+id/frLayout"></FrameLayout>


</RelativeLayout>

thumbnail.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ProgressBar
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/prgb_progress" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="ClickMe!"
        android:id="@+id/tvClickMe"
        android:layout_gravity="center_horizontal"
        android:textIsSelectable="false" />
</FrameLayout>

What it does: We have here one base class, it operates with representation of views and populating progress bars. It has field to work with current items (that holds progress bar values), every time when we switching between fragments this field is updated to respective values of Fragment1 or Fragment2, those fragments have static fields to hold their own data so it can be changed and used.

The thing with Thread and some other code is just to show that it's works and for better understanding.

I hope it will help.

PoC - https://youtu.be/uKGeX40z_mA :)




回答2:


As an abstract blueprint you could add a download Service to your app and let it to download your materials.

For communicating with this service you might want to declare it as a bind-able service so that whenever user switch to that fragment your activity can bind to this service and see what is going on.

Using this way, you can report download progress to user and also you no longer need sending broadcasts.



来源:https://stackoverflow.com/questions/32668285/how-to-retain-progress-bar-state-while-switching-the-fragments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!