必须从UI线程调用方法,当前推断的线程是worker

时间:2016-05-25 05:30:55

标签: java android multithreading android-fragments canvas

我想在画布上绘制圆圈。目前我可以在按钮点击时执行此操作,但是在加载Fragment时我也需要执行相同的操作。以下是我的Fragment代码。

public class StepTwentyOneFragment extends Fragment {

    private CanvasView customCanvas;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.step21_fragment, container, false);
        customCanvas=(CanvasView)v.findViewById(R.id.signature_canvas);

        final Button button1=(Button)v.findViewById(R.id.step18button1);


        float radius=(customCanvas.getCanvasWidth()/2) - ((customCanvas.getCanvasWidth()/2)/100)*60;
        new MyAsyncTask(customCanvas).execute();

        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if(v.getId()==R.id.step18button1){

                    float radius=(customCanvas.getCanvasWidth()/2) - ((customCanvas.getCanvasWidth()/2)/100)*60;
                    customCanvas.drawCircle(radius);
                    Log.d("An_Width", "" + customCanvas.getCanvasWidth());
                    Log.d("An_Height" ,""+ customCanvas.getCanvasHeight());

                    v.setBackgroundResource(R.drawable.button_border_5);
                    button1.setTextColor(Color.WHITE);


                }
            }
        });






        return v;
    }

    public static StepTwentyOneFragment newInstance() {

        StepTwentyOneFragment f = new StepTwentyOneFragment();
        Bundle b = new Bundle();

        f.setArguments(b);

        return f;
    }


    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(isVisibleToUser) {
            Activity a = getActivity();
            if(a != null) a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    }

    public class MyAsyncTask extends AsyncTask<Void, Void, Void> {

        CanvasView myTaskView;

        MyAsyncTask(CanvasView v){
            myTaskView = v;
        }

        @Override
        protected Void doInBackground(Void... arg0) {

            myTaskView.drawCircle(150);
            return null;
        }

    }

}

以下是我的Canvas代码

public class CanvasView extends View {

    public int width;
    public int height;
    private Bitmap mBitmap;
    private Canvas mCanvas;
    private Path mPath;
    Context context;
    private Paint mPaint;
    private float mX, mY;
    private static final float TOLERANCE = 5;
    private int canvasHeight, canvasWidth;
    private float radius;

    public CanvasView(Context c, AttributeSet attrs) {
        super(c, attrs);
        context = c;

        mPath = new Path();

        mPaint = new Paint();
        mPaint.setStrokeWidth(3);
        mPaint.setColor(Color.CYAN);
    }

    // override onDraw
    @Override
    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);

        mCanvas=canvas;

        Drawable d = getResources().getDrawable(R.drawable.circle_1);

        canvasHeight= canvas.getHeight();
        canvasWidth= canvas.getWidth();

        Log.d("Height - "," / "+canvas.getHeight());
        Log.d("Width - "," / "+canvas.getWidth());

//         DisplayMetrics displaymetrics = new DisplayMetrics();
//        ((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
//        int height = displaymetrics.heightPixels;
//        int width = displaymetrics.widthPixels;

        float h=canvasHeight/2;
        float w=canvasWidth/2;


        d.setBounds(0, 0, canvasWidth, canvasHeight);
        d.draw(canvas);

        canvas.drawCircle(w, h, radius, mPaint);
    }

    public void clear2(){
        radius=0;
        //important. Refreshes the view by calling onDraw function
        invalidate();

    }

    public void drawCircle(float radius1) {

        radius=radius1;
        //important. Refreshes the view by calling onDraw function
        invalidate();

    }

    public int getCanvasHeight()
    {
        return canvasHeight;
    }

    public int getCanvasWidth()
    {
        return canvasWidth;
    }

}

然而,在FragmentMyAsyncTask内,它显示代码行Method drawCircle must be called from the UI thread, currently inferred thread is worker的错误myTaskView.drawCircle(150);

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

如果要在doInBackground()中实现,则无法在UI线程上显示任何内容。它是为了后台任务。要更新UI,必须在postexecute()中实现方法。

详细了解AsyncTask:https://developer.android.com/reference/android/os/AsyncTask.html

清除您的概念,然后使用AsynTask会更容易。

AsyncTask的基本结构:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }