问题
I'm new in Android and not really knowing how to deal this problem: I have an AsyncTask which reads a position (X,Y,Z) from a XML file. As this position changes every second, I want, after I push a button (called with "StartListener") to read and draw every new position CONTINUOUSLY and stop reading it when I press the button again...
Somebody can help me? - Here is a part of my MainActivity
(For the moment my app reads and draws a position only when I press the button...)
private OnClickListener StartListener = new OnClickListener() {
@Override
public void onClick(View v) {
TextView ButText = (TextView)findViewById(R.id.buttonStart);
String value=ButText.getText().toString();
if(value.equals("Start positioning")){
ButText.setText("Stop positioning");
new PositionAsync().execute(); //read data from XML file
}
else if(value.equals("Stop positioning")){
ButText.setText("Start positioning");
//new PositionAsync().cancel(true);
}
}
}; // END LISTENER START BUTTON
// READ XML FILE
class PositionAsync extends AsyncTask<Void, Void, Void> {
XMLHelper helper;
@Override
protected Void doInBackground(Void... arg0) {
helper = new XMLHelper();
helper.get();
return null;
}
@Override
protected void onPostExecute(Void result) {
Paint paintBlack = new Paint(); paintBlack.setAntiAlias(true); paintBlack.setColor(Color.BLACK);
BitmapFactory.Options myOptions = new BitmapFactory.Options();
myOptions.inDither = true;
myOptions.inScaled = false;
myOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;// important
myOptions.inPurgeable = true;
File ImageSource = new File("/sdcard/app_background3.jpg");
Bitmap bitmap2 = BitmapFactory.decodeFile(ImageSource.getAbsolutePath(),myOptions);
Bitmap workingBitmap = Bitmap.createBitmap(bitmap2);
Bitmap mutableBitmap2 = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas2 = new Canvas(mutableBitmap2);
float RoomWidthPx = canvas2.getWidth();
float RoomHeightPx = canvas2.getHeight();
float RoomXmeter = (float) 9.3;
float RoomZmeter = (float) 14.7;
for (PositionValue position : helper.positions) {
String PosX = position.getPositionX(); String PosY = position.getPositionY(); String PosZ = position.getPositionZ();
float x = Float.valueOf(PosX); float y = Float.valueOf(PosY); float z = Float.valueOf(PosZ);
float xm = x*RoomWidthPx/RoomXmeter;
float zm = z*RoomHeightPx/RoomZmeter;
canvas2.drawCircle(xm, zm, 25, paintBlack);
ImageView imageView = (ImageView)findViewById(R.id.imageView1);
imageView.setAdjustViewBounds(true);
imageView.setImageBitmap(mutableBitmap2);
// SAVE DRAWINGS INTO FILE
FileOutputStream fos = null;
try {
fos = new FileOutputStream ("/sdcard/app_background3.jpg");
mutableBitmap2.compress (Bitmap.CompressFormat.JPEG, 95, fos);
} catch (Throwable ex) {ex.printStackTrace (); }
};
}
} //END READ XML FILE
回答1:
I think you are doing too many task in just one second. You could, instead, prepare all heavy staff in the onPreExecute()
of the AsyncTask, read the XML and do the painting in the doInBackground()
, resfresh the ImageView in the onProgressUpdate()
and finally, when the task is done, save the image to the sdcard
.
I've modified your Asynctask
to accomplish the above scenario, I've not tested it but it gives you the idea.
In the onCreate()
method of your activity you start the AsyncTask just once. It stays executing or sleeping until you set the Quit_Task variable to true. When the button is pressed you toggle the variable Do_Drawing: Do_Drawing=!Do_Drawing;
and that's it.
private boolean Do_Drawing = false;
private boolean Quit_Task = false;
// READ XML FILE
class PositionAsync extends AsyncTask<Void, Void, Void>
{
Paint paintBlack;
BitmapFactory.Options myOptions;
Bitmap mutableBitmap2;
Canvas canvas2;
XMLHelper helper;
void Sleep(int ms)
{
try
{
Thread.sleep(ms);
}
catch (Exception e)
{
}
}
@Override
protected void onPreExecute()
{
// Prepare everything for doInBackground thread
paintBlack = new Paint();
paintBlack.setAntiAlias(true);
paintBlack.setColor(Color.BLACK);
myOptions = new BitmapFactory.Options();
myOptions.inDither = true;
myOptions.inScaled = false;
myOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;// important
myOptions.inPurgeable = true;
File ImageSource = new File("/sdcard/app_background3.jpg");
Bitmap bitmap2 = BitmapFactory.decodeFile(ImageSource.getAbsolutePath(), myOptions);
Bitmap workingBitmap = Bitmap.createBitmap(bitmap2);
mutableBitmap2 = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
canvas2 = new Canvas(mutableBitmap2);
helper = new XMLHelper();
}
@Override
protected Void doInBackground(Void... arg0)
{
while (!Quit_Task)
{
// Sleep until button is pressed or quit
while (!Do_Drawing)
{
Sleep(1000);
if (Quit_Task)
return null;
}
float RoomWidthPx = canvas2.getWidth();
float RoomHeightPx = canvas2.getHeight();
float RoomXmeter = (float) 9.3;
float RoomZmeter = (float) 14.7;
// keep drawing until button is pressed again or quit
while (Do_Drawing)
{
if (Quit_Task)
return null;
helper.get();
for (PositionValue position : helper.positions)
{
String PosX = position.getPositionX();
String PosY = position.getPositionY();
String PosZ = position.getPositionZ();
float x = Float.valueOf(PosX);
float y = Float.valueOf(PosY);
float z = Float.valueOf(PosZ);
float xm = x * RoomWidthPx / RoomXmeter;
float zm = z * RoomHeightPx / RoomZmeter;
canvas2.drawCircle(xm, zm, 25, paintBlack);
}
this.publishProgress((Void) null);
Sleep(1000);
}
}
return null;
}
@Override
protected void onProgressUpdate(Void... progress)
{
// once all points are read & drawn refresh the imageview
try
{
ImageView imageView = (ImageView) findViewById(R.id.imageView1);
imageView.setAdjustViewBounds(true);
imageView.setImageBitmap(mutableBitmap2);
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
protected void onPostExecute(Void result)
{
// SAVE DRAWINGS INTO FILE once the task is done.
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "app_background3.jpg");
mutableBitmap2.compress(Bitmap.CompressFormat.JPEG, 95, fos);
}
catch (Throwable ex)
{
ex.printStackTrace();
}
}
} // END READ XML FILE
回答2:
you can use Handlers to deal with this:
private boolean isBusy = false;//this flag to indicate whether your async task completed or not
private boolean stop = false;//this flag to indicate whether your button stop clicked
private Handler handler = new Handler();
public void startHandler()
{
handler.postDelayed(new Runnable()
{
@Override
public void run()
{
if(!isBusy) callAysncTask();
if(!stop) startHandler();
}
}, 1000);
}
private void callAysncTask()
{
//TODO
new PositionAsync().execute();
}
set isBusy to true when the async task in doInBackground and set it back to false in the last line of onPostExecute.
when you click stop button set stop to true, when click start button set stop to false
来源:https://stackoverflow.com/questions/18702298/android-how-to-run-an-asynctask-every-second