首页 > 解决方案 > 用 SharedPreferences 中的对象填充的 RecyclerView 缓慢且滞后

问题描述

我正在构建一个具有 RecyclerView 的应用程序,其中包含从 SharedPreferences 检索到的对象。不幸的是,RecyclerView 在绑定时滞后。

这是我的适配器

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

    private List<Shift> mDataSet;
    private Context mContext;
    private static final String TAG = "ShiftAdapter";
    public int previousExpandedPosition = -1;
    public int mExpandedPosition = -1;
    private static SharedPreferences mPrefs;
    private LinearLayout mShiftIn;
    private LinearLayout mShiftOut;
    private Boolean isStart;
    private Date shiftIn;
    private Date shiftOut;
    private Date mDate;
    public EditText mshiftInText;
    public EditText mshiftOutText;
    public Date date;



    public ShiftAdapter(Context context, List<Shift> list) {
        mDataSet = list;
        mContext = context;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        public TextView mDate;
        public TextView mTime;
        public TextView mPay;
        public RelativeLayout mRelativeLayout;
        public LinearLayout mExepandableLayout;
        public Date mshiftIn;
        public Date mshiftOut;
        public EditText mshiftInText;
        public EditText mshiftOutText;
        public Button mUpdateButton;
        public Button mDeleteButton;



        public ViewHolder(View v) {
            super(v);
            mDate = (TextView) v.findViewById(R.id.date_TV);
            mTime = (TextView) v.findViewById(R.id.time_TV);
            mPay = (TextView) v.findViewById(R.id.pay_TV);
            mRelativeLayout = (RelativeLayout) v.findViewById(R.id.rel_layout);
            mExepandableLayout = (LinearLayout) v.findViewById(R.id.expandableLayout);
            mshiftInText = (EditText) v.findViewById(R.id.setShiftIn);
            mshiftOutText = (EditText) v.findViewById(R.id.setShiftOut);
            mUpdateButton = (Button) v.findViewById(R.id.updateButton);
            mDeleteButton = (Button) v.findViewById(R.id.deleteButton);
        }
    }

    @Override
    public ShiftAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(mContext)
                .inflate(R.layout.shift, parent, false);
        ViewHolder vh = new ViewHolder(itemView);
        return vh;
    }


    //TODO:Bind all the view elements to Shift Properties
        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int i) {

            // Format double
            String hours = new DecimalFormat("##.##").format(mDataSet.get(i).getHours());
            String pay = new DecimalFormat("##.##").format(mDataSet.get(i).getPay());
            //set the Text
            holder.mTime.setText(hours);
            holder.mDate.setText(mDataSet.get(i).dateToString());
            holder.mPay.setText(pay);
            Log.d(TAG, "onBindViewHolder: called");

//            new AsyncTask<>().ex


            //Expand mExapndableLayout
            final int position = i;
            final boolean isExpanded = position ==mExpandedPosition;
            holder.mExepandableLayout.setVisibility(isExpanded?View.VISIBLE:View.GONE);
            holder.itemView.setActivated(isExpanded);

//            //set shift Times
//            shiftIn = mDataSet.get(position).getInDate();
//            shiftOut = mDataSet.get(position).getInDate();



            if (isExpanded)
                previousExpandedPosition = position;

            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mExpandedPosition = isExpanded ? -1:position;
                    notifyItemChanged(previousExpandedPosition);
                    notifyItemChanged(position);
                }
            });

            //fill expandable layout
            holder.mshiftInText.setText(mDataSet.get(position).fullTimeToString(0));
            final EditText in = holder.mshiftInText;
            final EditText out = holder.mshiftOutText;

            //edit mShiftIn Text
            holder.mshiftInText.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    isStart =true;
                    timePickerDialog(in,out);
                }
            });
            holder.mshiftOutText.setText(mDataSet.get(position).fullTimeToString(1));

            //edit MshiftOut Text
            holder.mshiftOutText.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    isStart =false;
                    timePickerDialog(in,out);
                }
            });

            //updateButton onClick
            holder.mUpdateButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    try {
                        shiftIn = mDataSet.get(position).getInDate();
                        shiftOut = mDataSet.get(position).getOutDate();
                        if(Validate.getValidate().isDateValid(shiftIn,shiftOut)) {
                            SharedPrefs.getInstance(mContext).editShift(newShift(shiftIn, shiftOut),Integer.toString(position));
                            int length = SharedPrefs.getInstance(mContext).getLength() - 1;
                            if (SharedPrefs.getInstance(mContext).getShift(length) != null) {
                                Log.d(TAG, "Edit Shift onClick: Success");
                                SharedPrefs.getInstance(mContext).saveShiftList(SharedPrefs.getInstance(mContext).sortList(SharedPrefs.getInstance(mContext).getShiftList()));
                                ShiftsFragment.updateUI();
                                Toast.makeText(mContext, "success", Toast.LENGTH_SHORT).show();
                            }
                        } else {
                            mShiftOut.setBackgroundResource(R.drawable.red_border);
                            Toast.makeText(mContext, "error", Toast.LENGTH_SHORT).show(); }
                    } catch(Exception e){
                        Log.d(TAG, "onDateSelected: "+e.toString());
                        Toast.makeText(mContext,"update FAIL", Toast.LENGTH_SHORT).show();
                    }
                    // update the Shift
                }
            });
            holder.mDeleteButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    areYouSure(mExpandedPosition);
                }
            });

        }

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


    public Date timePickerDialog(EditText in,EditText out) {
        mshiftInText = in;
        mshiftOutText = out;
        new SingleDateAndTimePickerDialog.Builder(mContext)
                .title(mContext.getResources().getString(R.string.choose_time))
                .displayListener(new SingleDateAndTimePickerDialog.DisplayListener() {
                    @Override
                    public void onDisplayed(SingleDateAndTimePicker picker) {
                        if(!isStart) {
                            date = mDate;
                        }
                    }
                }).defaultDate(returnDate(date))
                .listener(new SingleDateAndTimePickerDialog.Listener() {
                    @Override
                    public void onDateSelected(Date date) {
                        mDate = date;
                        if (isStart) {
                            updateShiftIn(mDate);
                            mshiftInText.setText(dateToString(mDate));
                        } else {
                            updateShiftOut(mDate);
                            mshiftOutText.setText(dateToString(mDate));
                        }

                    }
                }).display();
        return mDate;
    }
    public String dateToString(Date date)
    {
        DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm");
        String string = df.format(date);
        return string;
    }
    private void updateShiftIn(Date date) {
        shiftIn = date;
    }

    private void updateShiftOut(Date date) {
        shiftOut = date;
    }
    private Date returnDate(Date date)
    {
        if(date!=null)
        {
            return date;
        }
        else return mDate;
    }

    private void areYouSure(int i)
    {
        final String position = Integer.toString(i);
        DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                switch (which){
                    case DialogInterface.BUTTON_POSITIVE:
                        Log.d(TAG, "onClick: isSure=true;");
                        SharedPrefs.getInstance(mContext).removeShift(position);
                        ShiftsFragment.updateUI();
                    case DialogInterface.BUTTON_NEGATIVE:
                        Log.d(TAG, "onClick: isSure= false");
                }
            }
        };

        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setMessage(mContext.getResources().getString(R.string.are_you_sure)).setPositiveButton(mContext.getResources().getString(R.string.confirm), dialogClickListener)
                .setNegativeButton(mContext.getResources().getString(R.string.cancel), dialogClickListener).show();
    }
    private Shift newShift(Date start,Date stop)
    {
        int id = SharedPrefs.getInstance(mContext).getLength();
        Shift shift = new Shift(dateToCalendar(start),dateToCalendar(stop),id);
        return shift;

    }

这是具有 RecyclerView 的片段

public class ShiftsFragment extends Fragment {
    private Toolbar mToolbar;
    private TimePicker timePicker1;
    private List<Shift> shiftList = new ArrayList<>();
    private RecyclerView recyclerView;
    private RelativeLayout relativeLayout;
    private RecyclerView.LayoutManager layoutManager;
    private LinearLayout mShiftIn;
    private LinearLayout mShiftOut;
    private Context mContext;
    private ShiftAdapter mAdapter;
    private MenuItem mAdd;
    private Menu optionsMenu;
    private LinearLayout mShiftAddLL;
    private SharedPreferences mPrefs;
    private static FragmentManager mFragmentManager;
    private static final String TAG = "ShiftsFragment";

    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.d(TAG,"Clicked");
        final View view = inflater.inflate(R.layout.shifts_layout,container,false);

        mToolbar = view.findViewById(R.id.topbar);
        mToolbar.inflateMenu(R.menu.toolbarmenu);
        mShiftAddLL = view.findViewById(R.id.add_shiftLayout);
        mAdd = mToolbar.getMenu().getItem(0);
        timePicker1 = (TimePicker) view.findViewById(R.id.timePicker);


        mFragmentManager = getFragmentManager();


        //TODO:Add a summary bar on the bottom.

        //get the context
        mContext = getContext();
        recyclerView = (RecyclerView) view.findViewById(R.id.shift_list);

        // Define a layout for RecyclerView
        layoutManager = new GridLayoutManager(mContext,1);
        recyclerView.setLayoutManager(layoutManager);

        // Initialize a new Shift array
        List<Shift> shiftList = initShifts();
        Log.d(TAG,"shift array initiated");
        // Initialize an array list from array
        // Initialize a new instance of RecyclerView Adapter instance
        mAdapter = new ShiftAdapter(mContext,shiftList);
        // Set the adapter for RecyclerView
        recyclerView.setAdapter(mAdapter);
        recyclerView.setNestedScrollingEnabled(false);
        recyclerView.setHasFixedSize(true);



        //Menu add button onClick
        //Opens Add_Shift_Fragment
        mAdd.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {
                Fragment selectedFragment = new Add_Shift_Fragment();
                getFragmentManager().beginTransaction().replace(R.id.fragment_container,
                        selectedFragment).commit();
                return false;
            }
        });


        return view;


    }

    //Initializes the Shift list from SharedPreferences and returns it.
    private List<Shift> initShifts() {
        return SharedPrefs.getInstance(mContext).getShiftList();

    }

    public static void updateUI()
    {
        Fragment selectedFragment = new ShiftsFragment();
        mFragmentManager.beginTransaction().replace(R.id.fragment_container,
                selectedFragment).commit();
    }


}

每次我启动 ShiftsFragment 时,都会出现一些跳帧,并且滚动时断时续。

也许我的 SharedPreferences 处理正在减慢速度?

public class SharedPrefs {

    private static SharedPrefs mSharedPrefs;
    private SharedPreferences mPrefs;
    private SharedPreferences.Editor mPrefsEditor;
    protected Context mContext;

    public static final String ID = "shiftList";

    private SharedPrefs(Context context) {
        mContext = context;
        mPrefs = context.getSharedPreferences(ID, Context.MODE_PRIVATE);
        mPrefsEditor = mPrefs.edit();
    }

    public static SharedPrefs getInstance(Context context) {

        if (mSharedPrefs == null) {
            mSharedPrefs = new SharedPrefs(context.getApplicationContext());
        }
        return mSharedPrefs;
    }

    public void saveShiftList(List<Shift> shiftList) {
        Gson gson = new Gson();
        String json = gson.toJson(shiftList);
        mPrefsEditor.putString(ID, json);
        mPrefsEditor.apply();
    }
    public void addShift (Shift shift)
    {
        List<Shift> shiftList= getShiftList();
        shiftList.add(shift);
        saveShiftList(shiftList);

    }
    //Replaced the shift@id with shift
    public void editShift(Shift shift,String id)
    {
        removeShift(id);
        addShift(shift);
    }
    public void removeShift(String id) {
        List<Shift> shiftList = getShiftList();
        int pos = Integer.parseInt(id);
        shiftList.remove(pos);
        saveShiftList(shiftList);
    }

    public void removeShift(int id) {
        List<Shift> shiftList = getShiftList();
        shiftList.remove(id);
        saveShiftList(shiftList);
    }

    public  Shift getShift(int id) {
        Gson gson = new Gson();
        List<Shift> shiftList;
        String json = mPrefs.getString(ID, null);
        Type type = new TypeToken<List<Shift>>() {
        }.getType();
        shiftList = gson.fromJson(json, type);
        Shift shift = shiftList.get(id);
        return shift;
    }

    public List<Shift> getShiftList() {
        Gson gson = new Gson();
        List<Shift> shiftList;
        String json = mPrefs.getString(ID, null);
        Type type = new TypeToken<List<Shift>>() {
        }.getType();
        shiftList = gson.fromJson(json, type);
        if (shiftList!=null) {
            return shiftList;
        } else{
            shiftList = new ArrayList<>();
            return shiftList;
        }

    }

    public List<Shift> sortList(List<Shift> shiftList)
    {
        Collections.sort(shiftList, new Comparator<Shift>() {
            public int compare(Shift shift1, Shift shift2) {
                if (shift1.getShiftStart() == null || shift2.getShiftStart() == null)
                    return 0;
                return shift1.getShiftStart().compareTo(shift2.getShiftStart());
            }
        });
        return shiftList;
    }

    public int getLength()
    {
        return  getShiftList().size();
    }
}

我只发现了图像加载的这个问题,而不仅仅是来自 SharedPrefs 的对象的字符串。

标签: androidandroid-recyclerview

解决方案


推荐阅读