我是Android编程新手,我已经开始学习一些小程序了。这个绘图程序直到我划出很多行(我不知道多少但大约10-20)这个数字取决于我绘制它的速度有多快(绘制更少的线条以便卡住)。当我开始调试并停止响应它停止响应时,它引导我到这一行:
private native void nativePollOnce(long ptr, int timeoutMillis); /non-static for callbacks/
不知道它是什么,是什么冻结程序,但这是我的程序:
Drawing.java
package com.appl.nikola.drawing;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Drawing extends AppCompatActivity implements View.OnTouchListener, SurfaceHolder.Callback {
public static SurfaceView surfaceView;
public static SurfaceHolder surfaceHolder;
Thread t1;
public static Coordinates cordinates;
public static List<Coordinates> listOfDrawing;
int staCrta;
public static Paint p;
public static boolean isItOK;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drawing);
//Definisem surfaceView
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
surfaceView.setOnTouchListener(this);
//Definisem surfaceHolder
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
//Definisem listu crtanja
listOfDrawing = new ArrayList<Coordinates>();
//Coordinates = {vrsta objekta:1-linija, 2-rucno, 3- pravougaonik, x1, y1, x2, y2}
cordinates = new Coordinates();
staCrta = 1;
cordinates.x1 = 5;
cordinates.x2 = 5;
cordinates.y1 = 6;
cordinates.y2 = 6;
cordinates.vrstaCrtanja = 1;
listOfDrawing.add(new Coordinates(cordinates.vrstaCrtanja,cordinates.x1,cordinates.y1,cordinates.y1,cordinates.y2));
cordinates.x1 = 7;
cordinates.x2 = 7;
cordinates.y1 = 8;
cordinates.y2 = 8;
cordinates.vrstaCrtanja = 1;
listOfDrawing.add(new Coordinates(cordinates.vrstaCrtanja,cordinates.x1,cordinates.y1,cordinates.y1,cordinates.y2));
//Definisem Paint: boja debljina
p = new Paint();
p.setColor(Color.YELLOW);
p.setStrokeWidth(3);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
switch (staCrta){
case 1:
cordinates.vrstaCrtanja = 1;
cordinates.x1 = event.getX();
cordinates.y1 = event.getY();
Log.d("Log1","Touch down");
break;
case 2:
break;
case 3:
break;
}
break;
case MotionEvent.ACTION_UP:
switch (staCrta){
case 1:
cordinates.x2 = event.getX();
cordinates.y2 = event.getY();
listOfDrawing.add(new Coordinates(cordinates.vrstaCrtanja,cordinates.x1,cordinates.y1,cordinates.x2,cordinates.y2));
Log.d("Log1", "Touch up");
break;
case 2:
break;
case 3:
break;
}
break;
case MotionEvent.ACTION_MOVE:
switch (staCrta){
case 1:
break;
case 2:
break;
case 3:
break;
}
break;
}
return true;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//Kada je surfaceView definisi i kreiraj thread t1
isItOK = true;
t1 = new Thread(new DrawingSurfaceLayout());
t1.start();
Log.d("Log1", "SurfaceCreated");
Log.d("Log1",Boolean.toString(isItOK));
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
isItOK = false;
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
t1 = null;
Log.d("Log1","Thread Stopped");
}
}
DrawingSurfaceLayout.java
package com.appl.nikola.drawing;
import android.graphics.Canvas;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Nikola on 4/25/2016.
*/
public class DrawingSurfaceLayout implements Runnable {
Canvas c;
Drawing drawing;
public DrawingSurfaceLayout() {
drawing = new Drawing();
}
@Override
public void run() {
try{
Log.d("Log1","run");
Log.d("Log1",Boolean.toString(drawing.isItOK));
while(drawing.isItOK){
if(!drawing.surfaceHolder.getSurface().isValid()){
Log.d("Log1","Surface not valid");
continue;
}
c = drawing.surfaceHolder.lockCanvas();
c.drawRGB(0, 0, 255);
List<Coordinates> listOfDrawing;
listOfDrawing = new ArrayList<Coordinates>();
listOfDrawing = drawing.listOfDrawing;
for(Coordinates x: listOfDrawing){
if(x.vrstaCrtanja == 1){//Linija
c.drawLine(x.x1,x.y1,x.x2,x.y2,drawing.p);
}
}
drawing.surfaceHolder.unlockCanvasAndPost(c);
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
Coordinates.java
package com.appl.nikola.drawing;
/**
* Created by Nikola on 4/25/2016.
*/
public class Coordinates {
float vrstaCrtanja;
float x1;
float y1;
float x2;
float y2;
public Coordinates() {
}
public Coordinates(float vrstaCrtanja, float x1, float y1, float x2, float y2) {
this.vrstaCrtanja = vrstaCrtanja;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
}
activity_drawing.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.appl.nikola.drawing.Drawing"
android:weightSum="100"
android:orientation="vertical">
<SurfaceView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="95"
android:id="@+id/surfaceView"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="5"
android:id="@+id/bMenu"/>
</LinearLayout>
编辑:
根据要求,这是我重现错误时弹出的内容
04-25 21:52:21.091: W/System.err(2488): java.util.ConcurrentModificationException
04-25 21:52:21.093: W/System.err(2488): at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
04-25 21:52:21.093: W/System.err(2488): at com.appl.nikola.drawing.DrawingSurfaceLayout.run(DrawingSurfaceLayout.java:37)
04-25 21:52:21.093: W/System.err(2488): at java.lang.Thread.run(Thread.java:818)
是的,当我点击主页按钮时弹出(应用冻结时回家)
04-25 21:57:07.227: I/ActivityManager(1533): START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10200000 cmp=com.android.launcher3/.Launcher (has extras)} from uid 1000 on display 0
04-25 21:57:07.243: D/(1533): HostConnection::get() New Host Connection established 0x9e2eb9a0, tid 1570
04-25 21:57:07.255: E/EGL_emulation(1187): tid 1187: eglCreateSyncKHR(1294): error 0x3004 (EGL_BAD_ATTRIBUTE)
04-25 21:57:07.305: I/InputDispatcher(1533): Dropping event because there is no touchable window at (195, 525).
04-25 21:57:07.357: W/EGL_emulation(2262): eglSurfaceAttrib not implemented
04-25 21:57:07.357: W/OpenGLRenderer(2262): Failed to set EGL_SWAP_BEHAVIOR on surface 0xa31bf620, error=EGL_SUCCESS
04-25 21:57:07.936: W/OpenGLRenderer(2262): Incorrectly called buildLayer on View: ShortcutAndWidgetContainer, destroying layer...
04-25 21:57:07.936: W/OpenGLRenderer(2262): Incorrectly called buildLayer on View: ShortcutAndWidgetContainer, destroying layer...
答案 0 :(得分:0)
在run()方法的DrawingSurfaceLayout中,您需要访问drawing.listOfDrawing,而另一个线程正在填充它。您可以使用迭代器来避免此问题。替换这个:
for(Coordinates x: listOfDrawing){
if(x.vrstaCrtanja == 1){//Linija
c.drawLine(x.x1,x.y1,x.x2,x.y2,drawing.p);
}
}
用这个:
for (Iterator<Coordinates> it = listOfDrawing.iterator(); it.hasNext();){
Coordinates x = it.next();
if (x.vrstaCrtanja == 1) {
it.drawLine(x.x1,x.y1,x.x2,x.y2,drawing.p);
}
}
它应该有效(我无法测试)。
答案 1 :(得分:0)
感谢您的帮助,我不知道多线程是如何工作的,但是这是我如何解决问题。我在同一个地方同步线程我使用相同的变量而不是:
listofDrawing = drawing.listofDrawing;
我设置了这个
synchronized (drawing.listOfDrawing){
for(Coordinates x: drawing.listOfDrawing){
listOfDrawing.add(x);
}
}
它就像一个魅力。我把这个答案放在一边,这样可能对某人有帮助。