Issue
I open a new fragment in my application, and I want to calculate the price and print it every second that passes (by asyncTask), but when I run the application stop working. can you help me to find the problem?
public class RandomDrive extends Fragment {
private Chronometer chronometer;
private Button start;
private Button stop;
private TextView price;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_random_drive, container, false);
chronometer = (Chronometer) v.findViewById(R.id.chronometer);
price = v.findViewById(R.id.see_price);
class SyncTaskCounter extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
double price = 0;
while (!isCancelled()) {
price = price + 0.05;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
printPrice(price);
}
return null;
}
@Override
protected void onCancelled() {
super.onCancelled();
}
}
final SyncTaskCounter asyncTaskCount;
asyncTaskCount = new SyncTaskCounter();
start = (Button) v.findViewById(R.id.start);
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
chronometer.setBase(SystemClock.elapsedRealtime());
chronometer.start();
asyncTaskCount.execute();
}
});
stop = (Button) v.findViewById(R.id.stop);
stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
chronometer.stop();
asyncTaskCount.cancel(true);
}
});
return v;
}
public void printPrice(double price1) {
price.setText("the price is: " + price1 + " shekel");
}
}
The problem is in asyncTask, because when I ran the function without asyncTask and calculated the price only at the end - the application run.
Solution
On Android you have to run all UI code on UI Thread. Code in AsyncTask in executed in other thread therefor it cannot call UI methods.
To do that you should use Handler (code will be called in UI thread): https://developer.android.com/reference/android/os/Handler
final Handler h=new Handler();
h.postDelayed(new Runnable() {
public void run() {
printPrice(price);
price = price + 0.05;
h.postDelayed(this, 1000); // call for next update
}
}, 1000);
I you have to use AsyncTask, then you should update UI from method: onProgressUpdate https://developer.android.com/reference/android/os/AsyncTask
class SyncTaskCounter extends AsyncTask<Void, Double, Void> {
@Override
protected Void doInBackground(Void... voids) {
double price = 0;
while (!isCancelled()) {
price = price + 0.05;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(price); // this instructs to call onProgressUpdate from UI thread.
}
return null;
}
@Override
protected void onProgressUpdate(Double... price) {
printPrice(price[0]); // this is called on UI thread
}
@Override
protected void onCancelled() {
super.onCancelled();
}
}
Answered By - RyszardTrojnacki
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.