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:
Should I create three fragments, or pass constant around to distinguish between fragment type as I use this constant to retrieve data from web?
Should I pass
fragmentmanger
orchildfragmentmanger
toviewpageradapter
, 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.
- In my case, would it be better to use
FragmentStatePagerAdapter
orFragmentPagerAdapter
?
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.
Why does the passed constant give the wrong number only in middle tab sometimes?
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:
What is the best location and method to use
TypeFace
,Animation
?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.