Choreographer:跳帧:应用程序可能在其主线程上做了太多工作

Choreographer: Skipped frames : The application may be doing too much work on its main thread

在我的 android 应用程序中,我收到“应用程序可能在其主线程上做了太多工作”的警告,并且 api 调用花费了太多时间来完成 response.I用 example.I 显示它有一个带有 2 个案例的单选按钮,每个案例都会在点击时进行 api 调用,结果将显示数据列表 users.Below 是我的代码。

protected void onCreate(Bundle savedInstanceState) {
    /**   Other code **/
    rdbGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
            pos = radioGroup.indexOfChild(findViewById(checkedId));
            switch (pos) {
                case 0:
                    if (screenType == 1) {
                        getClassTeacherList();
                    } else {
                        rcyTeachers.setVisibility(View.GONE);
                    }
                    fabAddClassTeacher.setTitle("Add class teacher");
                    return;
                case 2:
                    if (screenType == 1) {
                        getAcademicTeachersList();
                    } else {
                        rcyTeachers.setVisibility(View.GONE);
                    }
                    fabAddClassTeacher.setTitle("Add Teacher");
                    return;
                default:
            }
        }
    });

private void getClassTeacherList() {
    academicPeriod = (AcademicPeriod) mSpnPeriod.getItemAtPosition(keyPos);
    if (isServerReachable(getApplicationContext())) {
        classTeacherList = serverAuthenticateService.getClassTeacherList(selClass.getId(),academicPeriod.getId(), authtoken, getApplicationContext());
        if (AppBackupCache.checkToken == 200) {
            showClassTeacherList();
        } else if (AppBackupCache.checkToken == 401) {
            manager.invalidateAuthToken("com.lss.loop", authtoken);
            authtoken = null;
            final AccountManagerFuture<Bundle> future = manager.getAuthToken(mAccount, AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS, new Bundle(), true, null, null);
            new Thread(new Runnable() {
                public void run() {
                    try {
                        Bundle bnd = (Bundle) future.getResult();
                        authtoken = bnd.getString("authtoken");
                        if (authtoken != null) {
                            classTeacherList = serverAuthenticateService.getClassTeacherList(selClass.getId(),academicPeriod.getId(), authtoken, getApplicationContext());
                            if (AppBackupCache.checkToken == 200) {
                                showClassTeacherList();
                                return;
                            } else {
                                getMsgBox("Error", "Something went wrong");
                                return;
                            }
                        }

                        getMsgBox("", "Token not refreshed....");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
        AppBackupCache.checkToken = 401;
        return;
    }
    getMsgBox("No connection", "No connection");
}

public boolean isServerReachable(Context applicationContext) {
    ConnectivityManager connMan = (ConnectivityManager) applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = connMan.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnected()) {
        try {
            URL urlServer = new URL(strUrl);
            HttpURLConnection urlConn = (HttpURLConnection) urlServer.openConnection();
            urlConn.setConnectTimeout(3000); //<- 3Seconds Timeout
            urlConn.connect();
            return urlConn.getResponseCode() == 200;
        } catch (MalformedURLException e1) {
            return false;
        } catch (IOException e) {
            return false;
        }
    }
    return false;
    //return true;
}


private void showClassTeacherList() {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            if (classTeacherList.size() > 0) {
                rcyTeachers.setVisibility(View.VISIBLE);
                linLayColor1.setVisibility(View.VISIBLE);
                linLaySub.setVisibility(View.GONE);
                classTeacherGridAdapter = new ClassTeacherGridAdapter(ClassTeacherActivity.this, classTeacherList, fontFamily, screenType, 1);
                rcyTeachers.setAdapter(classTeacherGridAdapter);
                ViewCompat.setNestedScrollingEnabled(rcyTeachers, true);
                return;
            }
            rcyTeachers.setVisibility(View.GONE);
            linLayColor1.setVisibility(View.GONE);
        }
    });
}

ServerAuthenticateService.java :

@Override
public List<ClassTeacher> getClassTeacherList(int classId, int academicId, String authtoken, Context applicationContext) {
    HttpHeaders headers = new HttpHeaders();
    headers.set("Authorization", "bearer " + authtoken);
    MultiValueMap<String, String> map = new LinkedMultiValueMap();
    map.add("classId", String.valueOf(classId));
    map.add("academicId", String.valueOf(academicId));
    ResponseEntity<String> restRes = this.restTemplate.exchange(apiUrl + "/getClassTeacherList", HttpMethod.POST, new HttpEntity(map, headers), String.class, new Object[0]);
    if (restRes.getStatusCode() == HttpStatus.OK) {
        AppBackupCache.checkToken = ItemTouchHelper.Callback.DEFAULT_DRAG_ANIMATION_DURATION;
        String resBody = (String) restRes.getBody();
        Type listType = new TypeToken<List<ClassTeacher>>() {}.getType();
        List<ClassTeacher> allActPgmMap = (List) this.gson.fromJson(resBody, listType);
        return allActPgmMap;
    } else if (restRes.getStatusCode() == HttpStatus.UNAUTHORIZED) {
        AppBackupCache.checkToken = 401;
        return null;
    } else {
        AppBackupCache.checkToken = 402;
        return null;
    }
}

下面是我得到的变暖。

I/Choreographer: Skipped 687 frames!  The application may be doing too much work on its main thread.
I/OpenGLRenderer: Davey! duration=11662ms; Flags=0, IntendedVsync=1315104621338, Vsync=1326554620880, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=1326567046366, AnimationStart=1326567174126, PerformTraversalsStart=1326567180324, DrawStart=1326747726176, SyncQueued=1326760565187, SyncStart=1326761318573, IssueDrawCommandsStart=1326761742323, SwapBuffers=1326766654823, FrameCompleted=1326767746542, DequeueBufferDuration=298000, QueueBufferDuration=332000, 

 I/Choreographer: Skipped 682 frames!  The application may be doing too much work on its main thread.
 I/OpenGLRenderer: Davey! duration=11418ms; Flags=0, IntendedVsync=1354296057548, Vsync=1365662723760, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=1365665791303, AnimationStart=1365665859063, PerformTraversalsStart=1365665871094, DrawStart=1365707384015, SyncQueued=1365711047505, SyncStart=1365711676880, IssueDrawCommandsStart=1365712054224, SwapBuffers=1365714258860, FrameCompleted=1365715220318, DequeueBufferDuration=243000, QueueBufferDuration=341000, 

在我的应用程序中,我有很多 API 次调用,大多数时候我都会收到此警告,我应该怎么做才能避免这种情况并使我的请求和应用程序运行得更快?

如果我没记错的话,至少有一次你的 ServerAuthenticateServicegetClassTeacherList 方法在 onCheckedChange 回调时在主 (UI) 线程上被调用被调用。您应该将 web API 调用移动到另一个线程,这样主线程就不会“冻结”等待 web API 调用的结果。

来自 https://developer.android.com/guide/components/processes-and-threads :

... if everything is happening in the UI thread, performing long operations such as network access or database queries will block the whole UI. When the thread is blocked, no events can be dispatched, including drawing events. From the user's perspective, the application appears to hang. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous "application not responding" (ANR) dialog. The user might then decide to quit your application and uninstall it if they are unhappy.

编辑:isServerReachable 方法也不应在主线程上调用。

EDIT2:你可以尝试这种方式,虽然我不知道你的代码在另一个线程上被调用的所有含义:

private void getClassTeacherList() {
academicPeriod = (AcademicPeriod) mSpnPeriod.getItemAtPosition(keyPos);
new Thread(new Runnable() {
            public void run() {
if (isServerReachable(getApplicationContext())) {
    classTeacherList = serverAuthenticateService.getClassTeacherList(selClass.getId(),academicPeriod.getId(), authtoken, getApplicationContext());
    if (AppBackupCache.checkToken == 200) {
        showClassTeacherList();
    } else if (AppBackupCache.checkToken == 401) {
        manager.invalidateAuthToken("com.lss.loop", authtoken);
        authtoken = null;
        final AccountManagerFuture<Bundle> future = manager.getAuthToken(mAccount, AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS, new Bundle(), true, null, null);