5
\$\begingroup\$

I am working in project that uses a Tablayout inside fragment. I have three tabs that fetch data from web service. This part of the app shows questions.We have three categories: one for recent, the second for unanswered, and third for all questions view.

Here is my situation:

The web developer designed me a web service to return a question item. They all share the same structure, but the data changes according to requirement.

I have some questions:

  1. Should I create three fragments, or pass constant around to distinguish between fragment type as I use this constant to retrieve data from web?

  2. Should I pass fragmentmanger or childfragmentmanger to viewpageradapter, notice this tab's inside a fragment.

ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());

This is the fragment class, any tips on how to improve it would be appreciated.

public class Questions_Fragment extends Fragment  {

    private TabLayout mTablayout;
    private ViewPager mViewpager;

    public static Questions_Fragment newInstance() {
        Questions_Fragment fragment = new Questions_Fragment();
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.questions_layout, null);
        mViewpager = (ViewPager) v.findViewById(R.id.viewPager);
        setupViewPager(mViewpager);

        mTablayout = (TabLayout) v.findViewById(R.id.tabs);
        mTablayout.setupWithViewPager(mViewpager);

        return v;
    }

    private void setupViewPager(ViewPager mViewpager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
        adapter.addFrag( QuestionsFragModel.newInstance(VolleyRequestHandler.RECENT_INT) , getResources().getString(R.string.newest));
        adapter.addFrag( QuestionsFragModel.newInstance(VolleyRequestHandler.UNANSWER_INT) , getResources().getString(R.string.notanswered));
        adapter.addFrag( QuestionsFragModel.newInstance(VolleyRequestHandler.ALLPOSTS_INT) , getResources().getString(R.string.allposts));
        mViewpager.setAdapter(adapter);
    }

I have only three tabs, should I use FragmentStatePagerAdapter or FragmentPagerAdapter.

I read from this discussion and documentation that FragmentStatePagerAdapter stores all the fragments in memory, my fragments contain a little complex view card view with images and many textviews, that I show them and hide, according to each question.

  1. In my case, would it be better to use FragmentStatePagerAdapter or FragmentPagerAdapter?
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
    private List<Fragment> mFragmentList = new ArrayList<>();
    private List<String> mFragmentTitleList=  new ArrayList<>();

    public ViewPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    public void addFrag(Fragment fra , String title){
        mFragmentList.add(fra);
        mFragmentTitleList.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }
}

My question view here is the fragment handler:

Should I fetch data from web each time fragment created by this method getQuestionsPosts() according to passed constant, then create textview to reload data from web in case it fails.

  1. Why does the passed constant give the wrong number only in middle tab sometimes?

  2. I want to clear and reload data each time fragment created, is this good practice or I should load data and update in user request (Swipe to Refresh pattern)

public class QuestionsFragModel extends Fragment implements OnClickListener {

    private RecyclerView Ques_list;
    private ProgressBar list_prog;
    private ListViewAdapter adapter;
    private List<QuestionItem> Questions = new ArrayList<>();
    private TextView reload;
    private VolleyRequestHandler _VolleyRequestHandler;
    private int CONST_TYPE = 0;
    public static final String PASSED_INT = "passed_number";
    private CoordinatorLayout _coordiatelayout;


    static QuestionsFragModel newInstance(int type) {
        QuestionsFragModel f = new QuestionsFragModel();
        Bundle bundle = new Bundle();
        bundle.putInt(PASSED_INT , type);
        f.setArguments(bundle);
        return f;
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.question_layout, container, false);
        CONST_TYPE = getArguments() != null ? getArguments().getInt(PASSED_INT) : 7;
        _VolleyRequestHandler = new VolleyRequestHandler(getActivity());
        _coordiatelayout = (CoordinatorLayout) v.findViewById(R.id.coordiatelayout);

        Ques_list = (RecyclerView) v.findViewById(R.id.questionlist);
        Ques_list.setLayoutManager(new LinearLayoutManager(getActivity()));
        adapter = new ListViewAdapter(getActivity(), Questions);
        Ques_list.setAdapter(adapter);


        list_prog = (ProgressBar) v.findViewById(R.id.progressbar);
        reload = (TextView) v.findViewById(R.id.reload);

        getQuestationsPosts();

        reload.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View position) {
                getQuestationsPosts();
            }
        });

        final FloatingActionButton floatingView = (FloatingActionButton) v.findViewById(R.id.FloatingView);
        if (floatingView != null) {
            floatingView.setOnClickListener(this);
        }
        return v;
    }

    public void getQuestationsPosts() {
        API api = new API(getActivity());
        if (api.isNetworkConnected()) {
            list_prog.setVisibility(View.VISIBLE);
            reload.setVisibility(View.GONE);
            FetchQuestationsFromWeb();
        } else {
            Snackbar.make(_coordiatelayout, getResources().getString(R.string.nointernet), Snackbar.LENGTH_LONG).show();
            Ques_list.setVisibility(View.GONE);
            reload.setVisibility(View.VISIBLE);
        }
    }
    private void onSuccessResponse(Object response){
        list_prog.setVisibility(View.GONE);
        reload.setVisibility(View.GONE);
        Ques_list.setVisibility(View.VISIBLE);
        if(Questions != null){
            Questions.clear();
        }
        Questions = (List < QuestionItem>)  response;
        adapter = new ListViewAdapter(getActivity() ,Questions);
        Ques_list.setAdapter(adapter);
    }
    private void onErrorResponse(String error){
        list_prog.setVisibility(View.GONE);
        reload.setVisibility(View.VISIBLE);
        Snackbar.make(_coordiatelayout , error , Snackbar.LENGTH_LONG).show();
    }
    private void FetchQuestationsFromWeb() {

        _VolleyRequestHandler.HandleRequests(Request.Method.POST , CONST_TYPE, null, new VolleyResponseCallBack() {
            @Override
            public void RequestSuccess(Object response) {
                onSuccessResponse(response);
            }

            @Override
            public void RequestFailed(String error) {
                onErrorResponse(error);
            }
        });
    }

    @Override
    public void onClick(View arg0) {
        startActivity(new Intent(getActivity(), Add_Question.class));
    }


}

The List adapter is where all fragments get their view.

I am new to recycling views, so I am not sure what the best practice relating the Typeface and animation on it. I also have some questions about this as well:

  1. What is the best location and method to use TypeFace, Animation?

  2. Why do some items show different behaviour as I mentioned?

public class ListViewAdapter extends RecyclerView.Adapter<ListViewAdapter.ViewHolder> {

    private Context _Context;

    private List<QuestionItem> Questions = new ArrayList<>();
    private API api;
    private int num;
    private int lastPosition = -1;
    public static final String BASE_POST_URl = "url....";


    public ListViewAdapter(Context context, List<QuestionItem> Questions) {
        this._Context = context;
        this.Questions = Questions;
        api = new API(context);
    }

    public ListViewAdapter(Context context, List<QuestionItem> Questions,
                           int num) {
        this._Context = context;
        this.Questions = Questions;
        this.num = num;
        api = new API(context);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(_Context);
        View itemView = inflater.inflate(R.layout.question_row, parent, false);
        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {
        Typeface tf = Typeface.createFromAsset(_Context.getAssets(),
                "fonts/GE_SS_Two_Bold.otf");
        Typeface tfreg = Typeface.createFromAsset(_Context.getAssets(),
                "fonts/GE_SS_Two_Light.otf");

        ImageLoader _ImageLoader = MySingleton.getInstance(_Context).getmImageLoader();

        if (Questions.get(position).user.userimageURL != null) {
            if (!Questions.get(position).user.getUserimageURL().isEmpty()) {
                //holder.userimageprog.setVisibility(View.VISIBLE);
                holder.imageView.setImageUrl(Profile_Fragment.BASE_URL + Questions.get(position).user.getUserimageURL(), _ImageLoader);
            }
        }

        if(Questions.get(position).Que_image_url != null){
            if (!Questions.get(position).getQue_image_url().isEmpty()) {
                holder._FrameLayout.setVisibility(View.VISIBLE);
                holder.post_img.setVisibility(View.VISIBLE);
                //holder.post_img_pro.setVisibility(View.VISIBLE);
                holder.post_img.setImageUrl(BASE_POST_URl + Questions.get(position).getQue_image_url(), _ImageLoader);
            }
        }

        holder.imageView.setDefaultImageResId(R.drawable.profile);
        holder.username.setTypeface(tf);
        holder.desc.setTypeface(tfreg);
        holder.Date.setTypeface(tfreg);
        holder.AnswersCount.setTypeface(tfreg);

        if(Questions.get(position).user.username != null){
            holder.username.setText(Questions.get(position).user.username);
        }
        if(Questions.get(position).Que_Content != null){
            holder.desc.setText(Questions.get(position).Que_Content);
        }
        if(Questions.get(position).category != null){
            holder.Category.setText(Questions.get(position).category);
        }

        if(Questions.get(position).Que_Date != null){
            holder.Date.setText(Questions.get(position).Que_Date);
        }

        if (!Questions.get(position).getComment().isEmpty()) {
            holder.arrow.setVisibility(View.VISIBLE);
            holder.AnswersCount.setVisibility(View.VISIBLE);
            holder.AnswersCount.setText(_Context.getResources().getString(R.string.youhaveanswer));
        }
        holder.arrow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent (_Context , ViewAnswers.class);
                intent.putExtra("passedobject", (Parcelable) Questions.get(position));
                _Context.startActivity(intent);
            }
        });


//      Animation animation = null;
//       animation = AnimationUtils.loadAnimation(_Context,
//                 R.anim.up_from_bottom);
//       animation.setDuration(500);
//          view.setAnimation(animation);
//            animation = null;
//
//      Animation animation = AnimationUtils.loadAnimation(_Context,
//              (pos > lastPosition) ? R.anim.up_from_bottom
//                      : R.anim.down_from_top);
//      view.startAnimation(animation);
//      lastPosition = pos;

    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemCount() {
        return Questions.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        protected NetworkImageView imageView, post_img;
        protected TextView desc, Category, username, Date, AnswersCount;
        protected ProgressBar userimageprog, post_img_pro;
        protected ImageView arrow;
        protected FrameLayout _FrameLayout;

        public ViewHolder(View itemView) {
            super(itemView);
            imageView = (NetworkImageView) itemView.findViewById(R.id.ques_user_img);
            desc = (TextView) itemView.findViewById(R.id.ques_content);
            Category = (TextView) itemView.findViewById(R.id.category);
            post_img = (NetworkImageView) itemView.findViewById(R.id.post_img);
            userimageprog = (ProgressBar) itemView.findViewById(R.id.userimgae_prog);
            post_img_pro = (ProgressBar) itemView.findViewById(R.id.post_prog);
            username = (TextView) itemView.findViewById(R.id.username_ques);
            Date = (TextView) itemView.findViewById(R.id.date);
            AnswersCount = (TextView) itemView.findViewById(R.id.answers_con);
            arrow = (ImageView) itemView.findViewById(R.id.imageView1);
            _FrameLayout = (FrameLayout)itemView.findViewById(R.id.frameLayout2);

        }
    }
}

question row view

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:cardview="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginLeft="8dp"
    android:layout_marginRight="8dp"
    cardview:cardBackgroundColor="@android:color/white"
    cardview:cardCornerRadius="5dp"
    cardview:cardElevation="2dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="10dp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/category"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="@color/blue"
            android:padding="10dp"
            android:text="TextView"
            android:textColor="@android:color/white" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal">

            <FrameLayout
                android:id="@+id/frameLayout1"
                android:layout_width="60dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginBottom="10dp"
                android:layout_marginLeft="4dp"
                android:layout_marginRight="4dp"
                android:layout_marginTop="10dp">

                <ProgressBar
                    android:id="@+id/userimgae_prog"
                    style="?android:attr/progressBarStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:visibility="gone" />

                <com.android.volley.toolbox.NetworkImageView
                    android:id="@+id/ques_user_img"
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    />
            </FrameLayout>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/username_ques"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="10dp"
                    android:text="Asmaa Samir"
                    android:textColor="@android:color/black"
                    android:textStyle="bold" />

                <TextView
                    android:id="@+id/date"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="10dp"
                    android:layout_marginTop="3dp"
                    android:text="2 days ago"
                    android:textColor="@android:color/black" />
            </LinearLayout>
        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:orientation="vertical">

            <TextView
                android:id="@+id/ques_content"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_margin="4dp"
                android:text="ماهى اسباب ضعف الرؤيه أمام الحاسوب؟"
                android:textColor="@android:color/black"
                android:textStyle="bold" />
        </LinearLayout>


        <FrameLayout
            android:id="@+id/frameLayout2"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_gravity="center"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:layout_marginTop="10dp"
            android:visibility="gone">

            <ProgressBar
                android:id="@+id/post_prog"
                style="?android:attr/progressBarStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:visibility="gone" />

            <com.android.volley.toolbox.NetworkImageView
                android:id="@+id/post_img"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:scaleType="centerCrop"
                android:visibility="visible" />
        </FrameLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_gravity="right"
            android:layout_weight="1"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/answers_con"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"
                android:layout_weight="1"
                android:text="32 إجابه"
                android:textColor="@android:color/black"
                android:visibility="gone" />

            <ImageView
                android:id="@+id/imageView1"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_gravity="center"
                android:src="@drawable/qustion_8"
                android:visibility="gone" />
        </LinearLayout>
    </LinearLayout>


</android.support.v7.widget.CardView>

Sorry for my long question but I appreciate each one help me.

\$\endgroup\$
1

1 Answer 1

1
\$\begingroup\$

I am glad to answer my question but I am looking for other options

  1. Should I create three fragments or pass a constant to distinguish between fragment type as I use this constant to retrieve data from web?

I think it's recommended to decrease number of classes as much as possible, if they do the same function, and this what occur in my case.

  1. Should I pass fragmentmanager or childfragmentmanager to viewpageradapter, notice this tab's inside a fragment.

According to documentation and discussion: I figure there differences between FragmentManager and ChildFragmentManager, FragmentManager for interacting fragment with activity , ChildFragmentManager for interacting between fragment inside one fragment, in my case I use ViewPager inside fragment then prefer ChildFragmentManger.

  1. In my case, is it better to use FragmentStatePagerAdapter or FragmentPagerAdapter?

After long researches in this topic [1] [2] , I can sum important difference between them FragmentStatePagerAdapter works well with heavy fragments as it store just states of fragment and completely removes fragment in transaction check source code line 139: mCurTransaction.remove(fragment).

On the other hand FragmentPagerAdapter pushes all fragments into memory this mean keep fragment in transaction in back stack it just detached them check source code line 117 mCurTransaction.detach((Fragment)object), so in my case as I use images I prefer FragmentStatePagerAdapter.

Notice if you user FragmentStatePagerAdapter you must check saved bundle and return passed data in case you pass any , in my case I should return passed int , bundle carry the same name used in your activity.

if (savedInstanceState != null) {
            CONST_TYPE = getArguments().getInt(PASSED_INT);
        } else {
            CONST_TYPE = getArguments() != null ? getArguments().getInt(PASSED_INT) : 0;
        }

this Answer Q4

Q5 I clear list and reload data each time fragment created , is this good practice or I should load data and update in user request (Swipe to Refresh pattern )

A5 I am not sure this time but I prefer SwipeRefreshLayout as user can refresh any time he want this quick tutorial for it .

Q6 what is the best place and way to use TypeFace , Animation ?

waiting someone answer it ....

Q7 why some items show different behaviour as I mention ?

A7 its the most important answer to me , why adapter give wrong view , it cause of using if statement , when using if in adapter you must use else

ex showing question image

     if(Questions.get(position).Que_image_url != null){
                if (!Questions.get(position).getQue_image_url().isEmpty()) {
                    holder._FrameLayout.setVisibility(View.VISIBLE);
                    holder.post_img.setVisibility(View.VISIBLE);
                    holder.post_img.setImageUrl(BASE_POST_URl + Questions.get(position).getQue_image_url(), _ImageLoader);
                }else{
                       holder._FrameLayout.setVisibility(View.GONE);
                    holder.post_img.setVisibility(View.GONE); 
                    }
            }else{
                  // extra code     
                   }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.