有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java RecyclerView在web服务手动同步后未刷新

在手动同步web服务后,我遇到了RecyclerView无法刷新的问题。 手动同步是通过在列表上向下滑动或点击ActionBar项目触发的。 手动同步使用截取请求以JSON格式检索数据,数据被解析并保存到SQLite数据库表中。同步日期时间还保存到SQLite数据库表中,稍后显示在片段的ActionBar子标题中。截击请求通过WorkManager OneTimeWorkRequest启动

问题是没有刷新RecyclerView列表。但是,如果我随后触发另一次手动同步,则ActionBar字幕和RecyclerView内容中的同步数据时间将更新,但会使用上一次手动同步中的数据。如果我从应用程序导航到设备的主屏幕,然后导航回我的应用程序,该应用程序现在显示最新手动同步的刷新数据,这一点就会变得很清楚

我看过很多关于这个问题的帖子(见下文),虽然我认为我已经改进了我的代码,但没有一个推荐的解决方案解决了这个问题

Recyclerview not call onCreateViewHolder RecyclerView not calling onCreateViewHolder or onBindView Recyclerview not call onCreateViewHolder RecyclerView is not refreshing

get JSON data from web and display using RecyclerView Recycler View appear blank and doesn't show SQLite data

RecyclerView onClick not working properly? Why doesn't RecyclerView have onItemClickListener()?

ListView not updating after web service Sync

其他资源包括: https://www.mytrendin.com/display-data-recyclerview-using-sqlitecursor-in-安卓/ https://medium.com/@studymongolian/updating-data-in-an-安卓-recyclerview-842e56adbfd8 https://www.youtube.com/watch?v=ObU-wCqoo2I https://www.youtube.com/watch?v=_0C18cbv6UE

因此,经过几个月的努力解决这个问题后,我现在转向StackOverflow社区寻求帮助

片段


    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_warning_list, container, false);

        mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.warning_swipe_refresh_layout);

        /* Set the Refresh Listener for the Swipe gesture */
        mSwipeRefreshLayout.setOnRefreshListener(
                new SwipeRefreshLayout.OnRefreshListener() {
                    @Override
                    public void onRefresh() {
                        SyncWarningsScheduler.oneTime();
                        updateUI();
                    }
                }
        );

        mWarningRecyclerView = (RecyclerView) view.findViewById(R.id.warning_recycler_view);

        /* Set the Toolbar to replace the default ActionBar, which has been hidden */
        if (mActivity != null) {
            Toolbar toolbar = (Toolbar) mActivity.findViewById(R.id.toolbar_abstract_single_fragment);
            mActivity.setSupportActionBar(toolbar);

            /* Set the toolbar title */
            ActionBar actionbar = mActivity.getSupportActionBar();
            if (actionbar != null) {
                actionbar.setDisplayHomeAsUpEnabled(true);
                actionbar.setTitle(getString(R.string.warning_list_fragment_toolbar_title));
            }
        }

        updateUI();
        return view;
    }


    @Override
    public void onResume() {
        super.onResume();
        updateUI();
    }


    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.fragment_warning_list, menu);
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.sync:
                mSwipeRefreshLayout.setRefreshing(true);
                SyncWarningsScheduler.oneTime();
                updateUI();

                return true;
            case R.id.information:
                /* Handle the Information Menu Item */
                FragmentManager fm = getFragmentManager();
                if (fm != null) {
                    WarningListFragmentTFBInformationDialogFragment dialog = new WarningListFragmentTFBInformationDialogFragment();
                    dialog.show(fm, TFB_INFO_DIALOG_TAG);
                }
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }


    private void updateUI() {
        WarningList warningList = WarningList.get(mActivity);
        List<Warning> warnings = warningList.getWarnings();

        if (mWarningAdaptor == null) {
            mWarningAdaptor = new WarningAdaptor(warnings);
            mWarningRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
            mWarningRecyclerView.setAdapter(mWarningAdaptor);
        } else {
            mWarningAdaptor.setWarnings(warnings);
            mWarningAdaptor.notifyDataSetChanged();
        }

        /* Update the ToolBar sub title to show the latest sync datetime */
        updateToolBarSubTitle();

        /* If visible, turn off the Swipe Refresh Progress Circle */
        if (mSwipeRefreshLayout != null && mSwipeRefreshLayout.isRefreshing()) {
            mSwipeRefreshLayout.setRefreshing(false);
        }
    }


    private void updateToolBarSubTitle() {
        SyncInformationList syncInformationList = SyncInformationList.get(mContext);
        Date syncDate = syncInformationList.getSyncDatetime(ORMSync.getWarningSyncTypeKey());

        ActionBar actionBar = mActivity.getSupportActionBar();
        if (actionBar != null) {
            actionBar.setSubtitle(DatabaseUtilities.formatDateSpecial(syncDate, true));
        }
    }


    private class WarningHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private Warning mWarning;
        private TextView mIssueForTextView;
        private TextView mDeclarationTextView;
        private View mStatusWarningViewLeft;
        private View mStatusWarningViewRight;

        public WarningHolder(LayoutInflater inflater, ViewGroup parent) {
            super(inflater.inflate(R.layout.list_item_warning, parent, false));
            /* Handlers a user press on a Warning */
            itemView.setOnClickListener(this);

            mIssueForTextView = (TextView) itemView.findViewById(R.id.issueFor_textView);
            mDeclarationTextView = (TextView) itemView.findViewById(R.id.declaration_textView);
            mStatusWarningViewLeft = (View) itemView.findViewById(R.id.status_warning_left);
            mStatusWarningViewRight = (View) itemView.findViewById(R.id.status_warning_right);
        }

        public void bind(Warning warning) {
            mWarning = warning;
            String issueForDate;

            issueForDate = DatabaseUtilities.formatDateSpecial(mWarning.getIssuedFor(), "d MMM yyyy");
            mIssueForTextView.setText(issueForDate);

            mDeclarationTextView.setText(mWarning.getTfbDeclaration());
            /* Set Declaration text colour */
            if (mWarning.isTfbStatus()) {
                /* If the day is a TFB set text color to Red */
                mIssueForTextView.setTextColor(getResources().getColor(R.color.red));
                mDeclarationTextView.setTextColor(getResources().getColor(R.color.red));
            }

            /* Set left and right status warning colour based on TFB status */
            mStatusWarningViewLeft.setBackgroundResource(mWarning.setStatusWarningColor());
            mStatusWarningViewRight.setBackgroundResource(mWarning.setStatusWarningColor());
        }

        @Override
        public void onClick(View v) {
            /* Process onClick */
            Intent intent = WarningPagerActivity.newIntent(mActivity, mWarning.getUID());
            startActivity(intent);
        }
    }


    private class WarningAdaptor extends RecyclerView.Adapter<WarningHolder> {
        private List<Warning> mWarnings;

        public WarningAdaptor(List<Warning> warnings) {
            mWarnings = warnings;
        }

        @NonNull
        @Override
        public WarningHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            LayoutInflater layoutInflater = LayoutInflater.from(mActivity);
            return new WarningHolder(layoutInflater, parent);
        }

        @Override
        public void onBindViewHolder(@NonNull WarningHolder holder, int position) {
            /* Bind data */
            Warning warning = mWarnings.get(position);
            holder.bind(warning);
        }

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

        public void setWarnings(List<Warning> warnings) {
            mWarnings.clear();
            mWarnings = warnings;
        }

        public List<Warning> getWarnings() {
            return mWarnings;
        }
    }
}

WorkManager oneTimeWorkRequest调度程序

public class SyncWarningsScheduler {
    private static final String TAG = "SyncWarningsScheduler";
    private static final String ONE_TIME_WORK_REQUEST = "OneTime";
    private static final String ONE_TIME_WORK_REQUEST_TAG = TAG + ONE_TIME_WORK_REQUEST;
    private static final String ONE_TIME_WORK_REQUEST_TAG_UNIQUE = ONE_TIME_WORK_REQUEST_TAG + "Unique";


    /* Getters and Setters */
    public static String getOneTimeWorkRequestTagUnique() {
        return ONE_TIME_WORK_REQUEST_TAG_UNIQUE;
    }

    public static void oneTime() {
        WorkManager workManager = WorkManager.getInstance();

        /* Create a Constraints object that defines when and how the task should run */
        Constraints constraints = new Constraints.Builder()
                .setRequiresCharging(false)
                .setRequiredNetworkType(NetworkType.CONNECTED)
                .build();

        /* Build the Input Data to pass to the Worker */
        Data inputData = new Data.Builder()
                .putString(SyncWarningsWorker.getWorkRequestTypeKey(), ONE_TIME_WORK_REQUEST)
                .build();

        /* Build the One Time Work Request */
        OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(SyncWarningsWorker.class)
                .setConstraints(constraints)
                /* Sets the input data for the ListenableWorker */
                .setInputData(inputData)
                .addTag(ONE_TIME_WORK_REQUEST_TAG)
                .build();

        workManager.enqueueUniqueWork(ONE_TIME_WORK_REQUEST_TAG_UNIQUE, ExistingWorkPolicy.REPLACE, oneTimeWorkRequest);
    }
}

工作经理工人

public class SyncWarningsWorker extends Worker {
    private static final String TAG = "SyncWarningsWorker";
    private Context mContext;
    private SQLiteDatabase mDatabase;
    private WarningList mWarningList;

    private static final String WORK_REQUEST_TYPE_KEY = "warningworkrequesttype";
    private static final String SYNC_DATE_TIME_KEY = "warningsyncdatetime";

    public SyncWarningsWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);

        /* Set the Context which must be the Application Context */
        mContext = context;

        mDatabase = IncidentsDatabaseHelper.get(context).getWritableDatabase();
        /* Get a refer to the WarningList Singleton */
        mWarningList = WarningList.get(context);
    }

    /* Getters and Setters */
    public static String getWorkRequestTypeKey() {
        return WORK_REQUEST_TYPE_KEY;
    }

    public static String getSyncDateTimeKey() {
        return SYNC_DATE_TIME_KEY;
    }


    @NonNull
    @Override
    public Result doWork() {
        /* Read passed-in argument(s) */
        String workRequestType = getInputData().getString(WORK_REQUEST_TYPE_KEY);
        LogUtilities.info(TAG, "doWork() - Processing EMV Warnings Work Request Type: " + workRequestType);

        try {
            downloadWarnings();

            Date now = new Date();
            long nowMilliSeconds = now.getTime();
            now.setTime(nowMilliSeconds);

            /* Update the WarningSyncType in SyncInformationList with the Warnings Sync Datetime */
            SyncInformationList syncInformationList = SyncInformationList.get(mContext);
            syncInformationList.updateSyncDatetime(ORMSync.getWarningSyncTypeKey(), now);

            Data syncDateTime = new Data.Builder()
                    .putLong(SYNC_DATE_TIME_KEY, nowMilliSeconds)
                    .build();

            return Result.success(syncDateTime);
        } catch (Exception e){
            LogUtilities.error(TAG, "doWork() - Can't download EMV Warnings data.\n\n" + e.toString());
            return Result.failure();
        }
    }

    private void downloadWarnings() {
        VolleyRequestQueue volleyRequestQueue;

        StringRequest request = new StringRequest(Request.Method.GET, JSONWarningsSchema.getTfbFdrJsonEndPoint(), onPostsLoaded, onPostsError);

        volleyRequestQueue = VolleyRequestQueue.get(mContext);

        volleyRequestQueue.addToVolleyRequestQueue(request);
    }

    private final Response.Listener<String> onPostsLoaded = new Response.Listener<String>() {
        ContentValues contentvalues;
        String noData = "NO DATA";

        @Override
        public void onResponse(String response) {
            /* Delete all the Warning records from the SQLite table */
            mWarningList.deleteAllWarnings();

            try {
                JSONObject jsonBody = new JSONObject(response);
                /* Within jsonBody is one nested JSON Array */
                JSONArray jsonArrayResults = jsonBody.getJSONArray(JSONWarningsSchema.getJsonRootArrayName());

                for (int i = 0; i < jsonArrayResults.length(); i++) {
                    /*
                     * Within jsonArrayResults are 10 sometimes 9 JSON Objects, the first 5 Objects are for TFB declarations and
                     * the last 5 (4) Objects are for FDR declarations.
                     */
                    JSONObject warningMetadata = jsonArrayResults.getJSONObject(i);

                    if (i < 5) {
                        /*
                         * The first 5 Objects are for Today and the next 4 days worth of TFB declarations. The TFB declaration in these Objects are
                         * used to INSERT new records into the warnings table using the issueFor date as the Alternate Primary Key.
                         * The FDR declarations for each day are defaulted to "NO DATA" to cater for the sometimes missing FDR data on the 5th day, this is
                         * to avoid null pointer errors when displaying the data in fragment_warning.
                         */
                        Warning warning = new Warning();

                        String issueForDate = warningMetadata.getString(JSONWarningsSchema.Keys.getIssueFor());
                        warning.setIssuedFor(JSONUtilities.stringToDate(issueForDate, JSONWarningsSchema.getJsonIssueForDateFormat()));

                        String status = warningMetadata.getString(JSONWarningsSchema.Keys.getStatus());
                        warning.setTfbStatus(JSONUtilities.stringToBoolean(status));

                        warning.setTfbDeclaration(warningMetadata.getString(JSONWarningsSchema.Keys.getDeclaration()));

                        /*
                         * Within the warningMetadata JSONObject is a JSONArray called declareList. Need to get the Array and
                         * iterate through the Array to extract the TFB warning for each District for this day.
                         * We know the exact number of JSONObjects in the declareList Array (ie an Object for each District).
                         */
                        JSONArray jsonArrayTFBDeclareList = warningMetadata.getJSONArray(JSONWarningsSchema.getJsonDeclareListArrayName());

                        /* Iterate through the TFB declareList Array */
                        for (int j = 0; j < jsonArrayTFBDeclareList.length(); j++) {
                            /* Get the JSON Object within the jsonArrayDeclareList Array */
                            JSONObject declareListMetadata = jsonArrayTFBDeclareList.getJSONObject(j);

                            /* Get the name and status pairs from the declareListMetadata Object */
                            String name = declareListMetadata.getString(JSONWarningsSchema.Keys.getDeclareListName());
                            String declareListStatus = declareListMetadata.getString(JSONWarningsSchema.Keys.getDeclareListStatus());

                            switch (name) {
                                case "Mallee":
                                    warning.setTfbMallee(declareListStatus);
                                    warning.setFdrMallee(noData);
                                    break;
                                case "Wimmera":
                                    warning.setTfbWimmera(declareListStatus);
                                    warning.setFdrWimmera(noData);
                                    break;
                                case "South West":
                                    warning.setTfbSouthWest(declareListStatus);
                                    warning.setFdrSouthWest(noData);
                                    break;
                                case "Northern Country":
                                    warning.setTfbNorthernCountry(declareListStatus);
                                    warning.setFdrNorthernCountry(noData);
                                    break;
                                case "North Central":
                                    warning.setTfbNorthCentral(declareListStatus);
                                    warning.setFdrNorthCentral(noData);
                                    break;
                                case "Central":
                                    warning.setTfbCentral(declareListStatus);
                                    warning.setFdrCentral(noData);
                                    break;
                                case "North East":
                                    warning.setTfbNorthEast(declareListStatus);
                                    warning.setFdrNorthEast(noData);
                                    break;
                                case "West and South Gippsland":
                                    warning.setTfbWestAndSouthGippsland(declareListStatus);
                                    warning.setFdrWestAndSouthGippsland(noData);
                                    break;
                                case "East Gippsland":
                                    warning.setTfbEastGippsland(declareListStatus);
                                    warning.setFdrEastGippsland(noData);
                                    break;
                                default:
                                    break;
                            } 
                        } 

                        contentvalues = ContentValueUtilities.getWarningListContentValues(warning, true);

                        mDatabase.beginTransaction();
                        try {
                            mDatabase.insert(ORMWarnings.getTableName(), null, contentvalues);
                            mDatabase.setTransactionSuccessful();
                        } catch (SQLiteException e) {
                            LogUtilities.error(TAG, "onPostsLoaded > onResponse - ERROR Inserting record into the '" + ORMWarnings.getTableName() + "' Table.\n\n" + e.toString());
                        } finally {
                            mDatabase.endTransaction();
                        } 
                    } else {
                        /*
                         * The last 5 or sometimes 4 Objects are for Today and the next 4 days worth of FDR declarations. The FDR declarations
                         * in these Objects are used to UPDATE FDR attributes in the warnings table using the issueFor date to find the existing warnings
                         * record.
                         */
                        String issueForFDR = warningMetadata.getString(JSONWarningsSchema.Keys.getIssueFor());
                        /* Ensure the retrieved issueFor date string is converted consistently */
                        Date issueForFDRDate = JSONUtilities.stringToDate(issueForFDR, JSONWarningsSchema.getJsonIssueForDateFormat());

                        /* Find the record in the warnings table by using the issueForFDRDate date. */
                        Warning warningExists = mWarningList.getWarning(issueForFDRDate);

                        /* Make sure a warning record has been returned */
                        if (warningExists != null) {
                            String issueAtDate = warningMetadata.getString(JSONWarningsSchema.Keys.getIssueAt());
                            warningExists.setFdrIssuedAt(JSONUtilities.stringToDate(issueAtDate, JSONWarningsSchema.getJsonIssueAtDateFormat()));

                            /*
                             * Within the warningMetadata JSONObject is a JSONArray called declareList. Need to get the Array and
                             * iterate through the Array to extract the FDR warning for each District for this day.
                             * We know the exact number of JSONObjects in the declareList Array (ie an Object for each District).
                             */
                            JSONArray jsonArrayFDRDeclareList = warningMetadata.getJSONArray(JSONWarningsSchema.getJsonDeclareListArrayName());

                            /* Iterate through the FDR declareList Array */
                            for (int z = 0; z < jsonArrayFDRDeclareList.length(); z++) {
                                /* Get the JSON Object within the jsonArrayFDRDeclareList Array */
                                JSONObject declareListMetadataFDR = jsonArrayFDRDeclareList.getJSONObject(z);

                                /* Get the name and status pairs from the declareListMetadataFDR Object */
                                String nameFDR = declareListMetadataFDR.getString(JSONWarningsSchema.Keys.getDeclareListName());
                                String declareListStatusFDR = declareListMetadataFDR.getString(JSONWarningsSchema.Keys.getDeclareListStatus());

                                switch (nameFDR) {
                                    case "Mallee":
                                        warningExists.setFdrMallee(declareListStatusFDR);
                                        break;
                                    case "Wimmera":
                                        warningExists.setFdrWimmera(declareListStatusFDR);
                                        break;
                                    case "South West":
                                        warningExists.setFdrSouthWest(declareListStatusFDR);
                                        break;
                                    case "Northern Country":
                                        warningExists.setFdrNorthernCountry(declareListStatusFDR);
                                        break;
                                    case "North Central":
                                        warningExists.setFdrNorthCentral(declareListStatusFDR);
                                        break;
                                    case "Central":
                                        warningExists.setFdrCentral(declareListStatusFDR);
                                        break;
                                    case "North East":
                                        warningExists.setFdrNorthEast(declareListStatusFDR);
                                        break;
                                    case "West and South Gippsland":
                                        warningExists.setFdrWestAndSouthGippsland(declareListStatusFDR);
                                        break;
                                    case "East Gippsland":
                                        warningExists.setFdrEastGippsland(declareListStatusFDR);
                                        break;
                                    default:
                                        break;
                                } 
                            }

                            contentvalues = ContentValueUtilities.getWarningListContentValues(warningExists, false);

                            mDatabase.beginTransaction();
                            try {
                                mDatabase.update(ORMWarnings.getTableName(), contentvalues, ORMWarnings.getUUIDColumn() + " = ?", new String[] {warningExists.getUID().toString()});
                                mDatabase.setTransactionSuccessful();
                            } catch (SQLiteException e) {
                                LogUtilities.error(TAG, "onPostsLoaded > onResponse - ERROR Updating record in the '" + ORMWarnings.getTableName() + "' Table.\n\n" + e.toString());
                            } finally {
                                mDatabase.endTransaction();
                            }
                        } else {
                            /* Something went wrong can't find warning record using the issueForFDRDate date */
                            LogUtilities.wtf(TAG, "onPostsLoaded > onResponse - " + issueForFDRDate.toString() + " warning record not found.\n\n");
                        } 
                    }
                }
            } catch (JSONException e) {
                LogUtilities.error(TAG, "onPostsLoaded > onResponse - Failed to Parse JSON body.\n\n" + e.toString());
            }
        }
    };


    private final Response.ErrorListener onPostsError = new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            LogUtilities.error(TAG, "onPostsError > onErrorResponse - Failed to download JSON body.\n\n" + error.toString());
        }
    }; 
} 

共 (2) 个答案

  1. # 1 楼答案

    在你的适配器中使用这个

     public void setWarnings(List<Warning> warnings) {
            mWarnings.clear();
            mWarnings = warnings;
            notifyDataSetChanged();
    
        }
    
  2. # 2 楼答案

    我想你应该更新一下;方法调用,因为当api调用时,它在后台工作。 或 你可以设定

    sleep(5000)
    updateUI();