如何避免应用程序可能在其主线程

时间:2017-08-08 04:44:26

标签: java android multithreading android-volley

我有两节课。一个是我的SettingsActivity和一个我的volley开展工作的课程。在我的网络服务中,它有很多数据需要转换为ArrayList并保存到我的Database;我有一个两个网络服务,在第一个完成之前调用,第二个开始之前它会延迟1秒。在Log之后,它总是会显示以下内容

 I/Choreographer: Skipped 226 frames!  The application may be doing too much work on its main thread.
 V/RenderScript: 0x5595d9d0e0 Launching thread(s), CPUs 8
 W/art: Suspending all threads took: 20.500ms
 W/SQLiteConnectionPool: A SQLiteConnection object for database '/data/data/com.app.myapp/databases/myDB.sqlite' was leaked!  Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
 I/art: Background partial concurrent mark sweep GC freed 38249(2025KB) AllocSpace objects, 2(968KB) LOS objects, 40% free, 16MB/26MB, paused 569us total 130.628ms
 I/Choreographer: Skipped 1528 frames!  The application may be doing too much work on its main thread.

我已经检查了我的数据库在使用后是否关闭,并且所有数据库都已关闭。但我仍然有database is leaked消息和Skipped xxx frames。我已经尝试创建一个新主题,我在SettingsActivity调用我的class时调用我的Volley类似

   btnSync.setOnClickListener(new View.OnClickListener(){
        public void onClick(View v) {

  Thread thread = new Thread(new Runnable(){
                @Override
                public void run(){
                    Parameter.parameterOneVolley(SettingsActivity.this, getApplicationContext());
                }
            });
    }
    });

尝试此操作后,我遇到了Can't create handler inside thread that has not called Looper.prepare()

然后也尝试使用这个

 runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    Parameter.parameterOneVolley(SettingsActivity.this, getApplicationContext());
                }
            });

但是我收到了Skipped frames消息。怎么解决?非常感谢您的帮助。

在我的Paramater课程中,我也打电话给ProgressDialog

这是我Paramter.parameterOneVolley

的代码
public static void parameterOneVolley(final Activity activity, final Context context) {

    final ProgressDialog pd = new ProgressDialog(activity);
    pd.setMessage("Fetching data....");
    pd.show();

    initializeDatabase(context);
    sqLiteAdapter = new SQLiteAdapter(activity);

    regionList = new ArrayList<Region>();
    divisionList = new ArrayList<Division>();


    final Response.Listener<JSONObject> listener = new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {

            try {

                JSONArray regionArr = response.getJSONArray("Region");
                JSONArray divisionArr = response.getJSONArray("Division");

                sqLiteAdapter.openToRead();



                    for(int i = 0; i < regionArr.length(); i++){
                        JSONObject regionObj = (JSONObject) regionArr.get(i);
                        Region region = new Region(regionObj.getInt("RegionId"),regionObj.getString("Region"));

                        regionList.add(region);


                    if(regionList.size()!=0) {
                        sqLiteAdapter.insertOrReplaceRegion(regionList);
                    }
                }


                    for(int i = 0; i < divisionArr.length(); i++){
                        JSONObject divisionObj = (JSONObject) divisionArr.get(i);
                        Division division = new Division(divisionObj.getInt("RegionId"),divisionObj.getInt("DivisionId"),divisionObj.getString("Division"));

                        divisionList.add(division);


                    if(divisionList.size()!=0) { sqLiteAdapter.insertOrReplaceDivision(divisionList);
                    }
                }

                sqLiteAdapter.close();

                if(pd != null && pd.isShowing()) {
                    pd.dismiss();
                }

            } catch (JSONException e) {
                e.printStackTrace();
                sqLiteAdapter.close();

                if(pd != null && pd.isShowing()) {
                    pd.dismiss();
                }

                Toast.makeText(context,
                        e.getMessage(), Toast.LENGTH_SHORT).show();
            }


            Toast.makeText(context, "Successfully synced.", Toast.LENGTH_SHORT).show();
                   //call next web service
                    final Handler handler = new Handler();
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            parameterTwoVolley(activity, context);
                    }
                    }, 1000);

        }
    };

    final Response.ErrorListener errorListener = new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            if(pd != null && pd.isShowing()) {
                    pd.dismiss();
                }

            if (error.networkResponse != null) {
                Log.d(TAG, "Error Response code: " + error.networkResponse.statusCode);
                Toast.makeText(context, error.networkResponse.statusCode, Toast.LENGTH_SHORT).show();
            }
            if (error instanceof TimeoutError || error instanceof NoConnectionError) {
                Log.d(TAG, "Error Response code: Timeout/NoConnection");
                Toast.makeText(context, "Timeout/NoConnection", Toast.LENGTH_SHORT).show();
            } else if (error instanceof AuthFailureError) {
                Log.d(TAG, "Error Response code: AuthFailureError");
                Toast.makeText(context, "AuthFailureError", Toast.LENGTH_SHORT).show();
            } else if (error instanceof ServerError) {
                Log.d(TAG, "Error Response code: ServerError");
                Toast.makeText(context, "ServerError", Toast.LENGTH_SHORT).show();
            } else if (error instanceof NetworkError) {
                Log.d(TAG, "Error Response code: NetworkError");
                Toast.makeText(context, "NetworkError", Toast.LENGTH_SHORT).show();
            } else if (error instanceof ParseError) {
                Log.d(TAG, "Error Response code: ParseError");
                Toast.makeText(context, "ParseError", Toast.LENGTH_SHORT).show();
            }

            if(pd != null && pd.isShowing()) {
                pd.dismiss();
            }
        }
    };
}

我尝试添加

activity.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    pd = new ProgressDialog(activity);
            pd.setMessage("Fetching data....");
            pd.show();
        }
                }
            });

activity.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    if(pd != null && pd.isShowing()) {
                        pd.dismiss();
                    }
                    Toast.makeText(context, "Successfully synced.", Toast.LENGTH_SHORT).show();
                }
            });

每次我使用Progress Dialog and Toast但我仍然遇到Skipped frames

还尝试使用ProgressBar来显示和隐藏它,但仍遇到skipped frames

1 个答案:

答案 0 :(得分:1)

在Android中,只有主线程(也称为UI线程)可以更新视图。这是因为在Android中UI工具包不是线程安全的。

当您尝试从工作线程更新UI时,Android会抛出此异常。如果要从另一个Thread更新UI,请使用Handler。

final Handler handler=new Handler();
new Thread(new Runnable() {
    @Override
    public void run() {
       //your code
        handler.post(new Runnable() {
            @Override
            public void run() {
                 Parameter.parameterOneVolley(SettingsActivity.this, getApplicationContext());
            }
        });
    }
}).start();