1

as in topic i have huge problem with optymalization of my activity. wireframe

At root level we have three controls: - Tab Layout, related with ViewPager - SurfaceView displaying plot for every fragment - and ViewPager itself

ViewPager displays fragments marked on the picture with red color. Every Fragment contains child fragment(green border) displaying List of elements with some controls responsible for edition. Elements are shown in ListView with custom adapter. I have two problems with this view.

First problem: I am using FragmenStatePagerAdapter for displaying views. I am storing instances of already created fragments inside adapter Map, to reuse them.

protected Map<Integer, Fragment> fragmentReferenceMap = new HashMap<Integer, Fragment>();
        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            if(!fragmentReferenceMap.containsKey(position)) {
                econetFragmentReferenceMap.put(position, MyFragment.newInstance(position));
            }
            return fragmentReferenceMap.get(position);
        }

When I swipe back to once created Fragment adapter returns created instance from map but even with that, onCreate() on my Fragment is called and whole fragment is created once again. I know that ViewPager has option for setting offscreen limit but isn't there any way to reuse this fragment view?

The second problem is that the whole proces of inflating ListView take to long. I tried changing offScreenLimit but when it is set to 7(max number of view pages) app freeze for a few seconds before showing activity, and i see lags in swipe animations. When I set it to other number lik 1 or 0, activity creating is faster but I loss a lot of frames when swiping. I am using all fragments data are stored in single data table. This approach is ease what to store all changes even if one of fragment is destroyed by ViewPager, so I would like to stay with that. I tried mocking data for adapter and I found that it is not making big affect on its creation time. I have also tires using async task to getView method for gathering whole data for single row and in onPostExecute method add it to view but it not giving satisfing result

This is my getView method:

@NonNull
    @Override
    public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        convertView = super.getView(position,convertView,parent);

        Spinner spinner = (Spinner) convertView.findViewById(R.id.UserMode);

        final TextView startTime = (TextView) convertView.findViewById(R.id.rangeStart);
        final TextView stopTime = (TextView) convertView.findViewById(R.id.rangeStop);

        if(getConverter() != null){

            List<String> values = getConverter().getValuesLabels();
            ArrayAdapter spinerAdapter = new ArrayAdapter(context, R.layout.custom_sec_spinner, R.id.tvSpinnerText, values);
            spinerAdapter.setDropDownViewResource(R.layout.spinner_dodatkowe_wiersz);
            spinner.setAdapter(spinerAdapter);

            spinner.setSelection(getConverter().getUserMode(modeIndex, position));

            spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
                    getConverter().setUserMode(modeIndex, position, position) ;
                }

                @Override
                public void onNothingSelected(AdapterView<?> adapterView) {

                }
            });

            int[] start = getConverter().getRangeStart(modeIndex, position);
            int[] end = getConverter().getRangeEnd(modeIndex, position);

            startTime.setText(start[0] + ":" + start[1]);
            stopTime.setText(end[0] + ":" + end[1]);

            startTime.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    TimePickerDialog mTimePicker;

                    int[] selectedTime = getConverter().getRangeStart(modeIndex, position);

                    mTimePicker = new TimePickerDialog(getContext(), new TimePickerDialog.OnTimeSetListener() {
                        @Override
                        public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) {
                            getConverter().setRangeStart(modeIndex, position, new int[]{selectedHour, selectedMinute});
                            startTime.setText(selectedHour + ":" + selectedMinute);
                        }
                    }, selectedTime[0], selectedTime[1], true);
                    mTimePicker.show();
                }
            });

            stopTime.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    TimePickerDialog mTimePicker;

                    int[] selectedTime = getConverter().getRangeEnd(modeIndex, position);

                    mTimePicker = new TimePickerDialog(getContext(), new TimePickerDialog.OnTimeSetListener() {
                        @Override
                        public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) {
                            getConverter().setRangeEnd(modeIndex, position, new int[]{selectedHour, selectedMinute});
                            stopTime.setText(selectedHour + ":" + selectedMinute);
                        }
                    }, selectedTime[0], selectedTime[1], true);
                    mTimePicker.show();
                }
            });
        }
        else{
            spinner.setEnabled(false);
        }

        return convertView;
    }

So, could you please tell me how can I optimaze my adapter and ListView to make it work faster, or give user the experience that nothing is lagging? I would be gratefull for any advice or even links to similar articles because I've been searching for whole day and tried almost everything. Thank you :)

Maciek
  • 61
  • 1
  • 8

1 Answers1

0
  1. Create list view on a background thread.
    Using a background thread ("worker thread") removes strain from the main thread so it can focus on drawing the UI. In many cases, using AsyncTask provides a simple way to perform your work outside the main thread. AsyncTask automatically queues up all the execute() requests and performs them serially. This behavior is global to a particular process and means you don’t need to worry about creating your own thread pool. reference link
  2. Try to Use Holder Class to increase performance
    A ViewHolder object stores each of the component views inside the tag field of the Layout, so you can immediately access them without the need to look them up repeatedly. First, you need to create a class to hold your exact set of views.

    View row=view;
    
    Holder holder=null;
    if(row==null){
        LayoutInflater inflater= (LayoutInflater)mContext.getSystemService(mContext.LAYOUT_INFLATER_SERVICE);
        row= inflater.inflate(R.layout.half_movie,viewGroup,false);
        holder=new Holder(row);
        row.setTag(holder);
    }else{
    
    
        holder= (Holder) row.getTag();
    
    
    
    }
    
phpdroid
  • 1,642
  • 1
  • 18
  • 36
  • I actually already have viewHolder but whole mechanism is hidden in base class, and u can't see it. – Maciek Mar 22 '18 at 13:17
  • I already tried AsyncTask but i guess the problem is that my task onPostExecute is called durning swipe animation and that freezes gui for split second. – Maciek Mar 22 '18 at 13:26