如何避免使用AsyncTask跳过帧

时间:2015-12-30 19:41:32

标签: android multithreading android-asynctask

我有一个名为table()的方法,它生成一个包含600行的表。当我在onCreate()中运行此方法时,即在主UI线程中,我从日志中收到一条消息:

I/Choreographer: Skipped 32 frames!  The application may be doing too much work on its main thread."

我发现,为了避免跳过帧,我应该使用AsyncTask。但是,我不知道如何在后台实现表生成?我无法将table()方法放在doInBackground(Void... params)中,因为doInBackground不适用于UI,但我也不能将此方法放在onPostExecute中,因为它会给我跳过帧。

AsyncTask中实现表格生成的正确方法是什么?

以下是table方法的代码,我在onCreate()

中运行它
public void table(){
    ScrollView scrollView = new ScrollView(this);
    HorizontalScrollView horizontalScroll = new HorizontalScrollView(this);
    TableLayout tableLayout = new TableLayout(this);
    tableLayout.setBackgroundColor(Color.BLACK);

    LayoutParams cellsParam = new LayoutParams(
            LayoutParams.MATCH_PARENT,
            LayoutParams.MATCH_PARENT);
    cellsParam.setMargins(1, 1, 1, 1);

    for(int i = 0; i < 600; i++){
        TableRow row = new TableRow(this);
            TextView wayTextView = new TextView(this);
            wayTextView.setText("text" + i);
            wayTextView.setBackgroundColor(Color.WHITE);
            wayTextView.setGravity(Gravity.CENTER);
            row.addView(wayTextView, cellsParam);

            tableLayout.addView(row);
        }
    horizontalScroll.addView(tableLayout);
    scrollView.addView(horizontalScroll);
    setContentView(scrollView);
}

2 个答案:

答案 0 :(得分:0)

有一种叫做#34; loop unrolling&#34;这对你有所帮助(但不是为了优化而做的,我们在这里做的就是将循环划分为一小块大小的“块”阻止UI线程。)

制作6个任务,每个执行100行:或10个60行任务(无论哪种情况最适合您的应用。)

我现在对此进行了测试,并按预期工作

&#39;静态&#39;从顶部算起的是:0 - &gt; (N-1)

package com.example.mike.myapplication;

import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    static int count = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int totalCount = 600;
        int numTasks = 10;

        int division = totalCount / numTasks ;

        // where did the other loop
        for (int i = 0; i < numTasks ; i++) {
            new UpdateRowsTask(this).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, Integer.valueOf(division));
        }
    }

    public void doLog(String str) {
        Log.d("TEST", str);
    }

    private static class UpdateRowsTask extends AsyncTask<Integer, Void, Void> {
        int maxCount ;
        MainActivity _activity;

        public UpdateRowsTask(MainActivity activity) {
            _activity = activity;
        }

        @Override
        protected Void doInBackground(Integer... params) {
            maxCount = params[0]; // adjustable
            return null;
        }

        protected void onPostExecute(Void result) {
            do {
                _activity.doLog("" + count);
                count++;
            }
             while  ((count % maxCount) != 0 ) ;
        }
    }   
}

我有&#39; log.d()&#39;作为我的&#34; UI线程&#34;操作,但您可以轻松地添加行。

答案 1 :(得分:0)

在阅读了有关AsyncTask的更多信息后,我得出结论,AsyncTask不适合解决我的问题。因为使用AsyncTask我无法更新table()中的用户界面并在onPostExecute中运行{{1}}方法也是错误的,因为这样做,我再次在主线程中再做太多工作将收到跳过的帧。