I need to do some validations sequentially and some of them involve complex database operations.
So, I need to do this in a separated thread of UI Thread, ok?
But some validations show messages to user, what need confirmation and
when user confirm, the next validation should be call.
This code example explains what I want to implement:
void makeValidation1(){
if(condition1Valid()){
makeValidation2();
}else{
DialogInterface.OnClickListener onClick = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
makeValidation2();
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setMessage("really want to do this?")
.setPositiveButton("Yes", onClick);
builder.create().show();
}
}
void makeValidation2(){
if(condition2Valid()){
}else{
//...
}
}
boolean condition1Valid() {
// complex database Operations
return false;
}
boolean condition2Valid() {
//complex database Operations
return false;
}
//...
void makeValidation9(){
//...
}
My question is: What the best way/pattern to implement this?
1 - Create one asyncTask for each validation? (I cant create only one AsyncTask, because confirmation messages can stop flux).
2 - Create a Runnable for each validation and create thread to run that when need call next validation?
3 - ???
edit
I tested this code #BinaryBazooka, but isnt work. Any help?
public class MainActivity extends Activity implements OnClickListener {
Thread mThread;
ProgressDialog mProgressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button button = new Button(this);
button.setText("Start");
setContentView(button, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
button.setOnClickListener(this);
}
#Override
public void onClick(View v) {
mThread = new Thread(new Runnable() {
#Override
public void run() {
validations();
}
});
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Start Thread?");
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.show();
mThread.run();
}
});
builder.create().show();
}
void validations(){
//this method go on separated thread
validation1();
validation2();
validation3();
}
void validation1(){
if(true){
final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setMessage("Validation 1 failed. Go validation 2?");
builder.setPositiveButton("Go", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
mProgressDialog.show();
//if user confirm, continue validation thread
mThread.notify();
}
});
builder.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
//if user cancel, stop validation thread
mThread.interrupt();
}
});
runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressDialog.hide();
builder.create().show();
}
});
try {
synchronized (mThread) {
//wait for user confirmation
mThread.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void validation2() {
if(true){
final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setMessage("validacao 2 failed. Go validation 3?");
builder.setPositiveButton("Go", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
mProgressDialog.show();
mThread.notify();
}
});
builder.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
mThread.interrupt();
}
});
runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressDialog.hide();
builder.create().show();
}
});
try {
synchronized (mThread) {
mThread.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void validation3() {
Log.i("TAG", "<<<<<<<<<< >>>>>>>>>>>>");
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, "finished", Toast.LENGTH_SHORT);
}
});
}
}
I would create a new thread and sleep it during these dialog calls, you can access the UI directly from within your runnable with..
runOnUiThread(new Runnable() {
public void run() {}
});
So something like..
Thread someThread = new Thread(new Runnable() {
#Override
public void run(){
runOnUiThread(new Runnable() {
public void run()
{
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(R.string.msg);
builder.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
someThread.notify();
}
});
AlertDialog alert = builder.create();
alert.show();
}
});
}
someThread.wait();
Works with AsyncTask. Ty.
Code:
public class MainActivity extends Activity implements OnClickListener {
//Thread mThread;
ProgressDialog mProgressDialog;
private ValidationsAsyncTask async;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button button = new Button(this);
button.setText("Start");
setContentView(button, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
button.setOnClickListener(this);
}
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Start Thread?");
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.show();
async = new ValidationsAsyncTask();
async.execute();
}
});
builder.create().show();
}
void validation1(){
if(true){
runOnUiThread(new Runnable() {
#Override
public void run() {
final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setMessage("Validation 1 failed. Go validation 2?");
builder.setPositiveButton("Go", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
mProgressDialog.show();
//if user confirm, continue validation thread
synchronized (async) {
async.notify();
}
}
});
builder.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
//if user cancel, stop validation thread
async.cancel(true);
}
});
mProgressDialog.hide();
builder.create().show();
}
});
Log.i("TAG - validation1", Thread.currentThread().getName());
try {
synchronized (async) {
//wait for user confirmation
async.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void validation2() {
if(true){
runOnUiThread(new Runnable() {
#Override
public void run() {
final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setMessage("validacao 2 failed. Go validation 3?");
builder.setPositiveButton("Go", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
mProgressDialog.show();
synchronized (async) {
async.notify();
}
}
});
builder.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
async.cancel(true);
}
});
mProgressDialog.hide();
builder.create().show();
}
});
try {
synchronized (async) {
async.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void validation3() {
runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressDialog.dismiss();
Toast.makeText(MainActivity.this, "finished", Toast.LENGTH_SHORT).show();
}
});
}
class ValidationsAsyncTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
validation1();
validation2();
validation3();
return null;
}
#Override
protected void onCancelled() {
Toast.makeText(MainActivity.this, "cancelled", Toast.LENGTH_LONG).show();
}
}
}
Related
When alertDialog.show gets called, it does pop up a dialog but it remains invisible. I have to tap on the screen until I happen to click the "OK" button that's on the alert even though it is not visibly showing.
public class RecordSignals extends Activity {
private ImageView pulseOxImage;
static AlertDialog poDialog;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(saveInstanceState);
pulseOxImage = new ImageView(this);
pulseOxImage.setImageDrawable(ContextCompat
.getDrawable(this,R.drawable.pulse_ox_animation));
poDialog = new AlertDialog.Builder(this).create();
...
}
final Runnable callback = new Runnable() {
#Override
public void run() {
Thread thread = new Thread() {
#Override
public void run() {
...
runOnUiThread(new Runnable() {
#Override
public void run() {
if (pulseOxArtifact >= 2 || pulseOxOutOfTrack >= 2 || pulseOxSensorAlarm >= 2) {
pulseOxStatus();
pulseOxImage.setVisibility(View.VISIBLE);
poDialog.show();
}
}
});
}
};
}
};
public void pulseOxStatus() {
poDialog.setView(pulseOxImage);
poDialog.setButton("OK", new DialogInterface.OnClicklistener() {
#Override
public void onClick(DialogInterface dialog, int which) {
poDialog.dismiss();
}
});
}
}
I want to show AlertDialog which is in other class in AsyncTask.
Example>
public class WardListAsyncTask extends AsyncTask<HashMap<String, String>, String, Object> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Object doInBackground(HashMap<String, String>... params) {
...
}
#Override
protected void onPostExecute(Object result) {
ConfirmAlertDialog(ez_WardList.this,"HI?");
//this method is in another Class & I want to use this method another Asynctask also..
}
and ConfirmAlertDialog is...
Context g_ctx;
String g_content;
public void ez_ConfirmAlertDialog(Context ctx, String content) {
this.g_ctx=ctx;
this.g_content=content;
runOnUiThread(new Runnable() {
#Override
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(g_ctx, AlertDialog.THEME_HOLO_LIGHT);
builder.setMessage(g_content).setPositiveButton(getString(R.string.kor_confirm),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
alertDialog.getWindow().setLayout(displayWidth / 2, LayoutParams.WRAP_CONTENT);
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(Color.rgb(10, 174, 239));
}
});
}
I think g_ctx.class.runonuiThread ... but I can't call runonuithread...
How can I solve it?
runOnUiThread method is present in Activity class. So should pass Activity into your class.
Example:
public class MyClass{
public void ez_ConfirmAlertDialog(Activity activity, String content) {
this.g_ctx=ctx;
this.g_content=content;
if(activity == null){
return;
}
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(g_ctx, AlertDialog.THEME_HOLO_LIGHT);
builder.setMessage(g_content).setPositiveButton(getString(R.string.kor_confirm),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
alertDialog.getWindow().setLayout(displayWidth / 2, LayoutParams.WRAP_CONTENT);
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(Color.rgb(10, 174, 239));
}
});
}
}
You can call it in main thread using handler
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// Your code here
}
});
is there a way to speed up the time when changing to another activity? or is there something wrong with my code?
public void connectedAnim(){
final Dialog dialog = new Dialog(LogIn.this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.connected);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
IVcon = (ImageView)dialog.findViewById(R.id.IVcon);
IVcon.setBackgroundResource(R.anim.connectedanim);
final AnimationDrawable animcon = (AnimationDrawable)IVcon.getBackground();
dialog.setCancelable(true);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
animcon.start();
Toast.makeText(getApplicationContext(), "Connected to HC-05", Toast.LENGTH_SHORT).show();
}
});
dialog.show();
new Handler().postDelayed(new Runnable() {
public void run() {
dialog.dismiss();
}
}, 1000);
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
Intent Menu = new Intent(LogIn.this, Menu.class);
LogIn.this.startActivity(Menu);
}
});
}
this is my method that is to be called when i connected my bluetooth to arduino, and i have an animation to it so after the animation comes the change to a new activity. this is how i called the connectedAnim() method
pwordtxt.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable sa) {
}
#Override
public void beforeTextChanged(CharSequence sa, int start,
int count, int after) {
}
#Override
public void onTextChanged(CharSequence sa, int start,
int before, int count) {
if (sa.length() == 4) {
progressDialog = ProgressDialog.show(LogIn.this, "", "Loading..");
password = getPass("password", getApplicationContext());
Runnable runnable = new Runnable() {
#Override
public void run() {
if ((password.equals(""))) {
if (s.toString().equals("1234")) {
findBT();
try {
openBT();
}
catch (IOException e) {}
beginListenForData();
handler.post(new Runnable() {
#Override
public void run() {
progressDialog.dismiss();
connectedAnim();
}
});
} else {
Toast.makeText(LogIn.this, "Incorrect Password", Toast.LENGTH_SHORT).show();
}
} else {
realpass = getPass("password", getApplicationContext());
if (s.toString().equals(realpass)) {
findBT();
} else {
Toast.makeText(LogIn.this, "Incorrect Password", Toast.LENGTH_SHORT).show();
}
}
}
};
new Thread(runnable).start();
}
}
});
}
I currently trying to show a progress dialog on OnclickListener of a Dialogbox since my items are taking too long to fetch from Server.
I use Async task as suggested here (Android progress dialog) and this post (android problem with progress dialog) to show progress dialog The progress dialog is shown , however the code returns exception when it goes to do background that " Looper is not set". And when I set looper nothing happens.
I am not sure at this stage what is it that I am doing wrong.
public void firstMethod()
{
final CustomObj obj = getCustomObj();//not imp
Messages.getInstance().showAlert(MainActivity.this, "message", false, new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
dialog.dismiss();
}
}, new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
gotoAnotherPge(obj);
}
});
}
public void gotoAnotherPge(final CustomObject obj)
{
final ProgressDialog pd = new ProgressDialog(MainActivity.this);
new AsyncTask<Object, Object, Boolean>()
{
protected void onPreExecute()
{
pd.setMessage(String.format(Statics.getText(MainActivity.this, R.raw.dictionary, "subscriptions_loading_unsubscribing")));
pd.show();
}
protected Boolean doInBackground(Object... params)
{
try{
Looper.prepare();
final LocalPopulator lp = new LocalPopulator(MainActivity.this, 0)
{
#Override
public void populate()
{
List<Serializable> items = Arrays.asList(getItemHere(obj));
List<Serializable> listItems = new ArrayList<Serializable>();
listItems.addAll(items);
Serializable[] sItems = listItems.toArray(new Serializable[menuItems.size()]);
result = sItems;
}
};
showNextPage(true, 1, 0, lp);
Looper.loop();
}catch (Exception e){
Log.e("tag", e.getMessage());
/*
* The task failed
*/
return false;
}
return true;
}
protected void onPostExecute(Boolean result)
{
pd.dismiss();
}
};
MainActivity.this.runOnUiThread (new Runnable()
{
#Override
public void run()
{
// dismiss the progressdialog
pd.dismiss();
}
});
}
I am implementing an android app.My problem no wis that when I send the data from the client to the server I want the client to know that the data was sent successfully. I have implemented an AlertDialog but when I send the data,I get a message "Can't create handler inside thread that has not called Looper.prepare()". I have attached my code below.
private void saveOrder(final Order order) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
getConnection().saveOrder(order);
handleSuccessSaveOrder();
}
catch (Exception exc) {
Log.d("--- ERROR ---", exc.getMessage());
handleException(exc.getMessage());
}
}
});
thread.start();
}
private void handleSuccessSaveOrder() {
showAlert(Farsi.Convert(" j "),R.drawable.warning);
//showActivity(MainMenuActivity.class);
}
private void showAlert(String message, int iconId) {
alert = new AlertDialog.Builder(ReviewOrderActivity.this);
alert.setTitle("Status Dialog");
alert.setMessage(message);
alert.setIcon(iconId);
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
showActivity(MainMenuActivity.class); } });
alert.show();
}
You cannot modify the ui from a non ui thread, use runOnUiThread:
private void saveOrder(final Order order) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
getConnection().saveOrder(order);
runOnUiThread(new Runnable() {
public void run() {
handleSuccessSaveOrder();
}
});
}
catch (Exception exc) {
Log.d("--- ERROR ---", exc.getMessage());
handleException(exc.getMessage());
}
}
});
thread.start();
}
you can not change UI from backgroung thread.
use like this
private void handleSuccessSaveOrder() {
ReviewOrderActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
showAlert(Farsi.Convert(" j "),R.drawable.warning);
}
});
//showActivity(MainMenuActivity.class);
}
Make Handler for display AlertDialog and Try below code instead of your above code, it will solve your problem.
private void saveOrder(final Order order) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
getConnection().saveOrder(order);
mHandler.sendEmptyMessage(0);
}
catch (Exception exc) {
Log.d("--- ERROR ---", exc.getMessage());
handleException(exc.getMessage());
}
}
});
thread.start();
}
public Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
handleSuccessSaveOrder();
}
};
private void handleSuccessSaveOrder() {
showAlert(Farsi.Convert(" j "),R.drawable.warning);
}
private void showAlert(String message, int iconId) {
alert = new AlertDialog.Builder(ReviewOrderActivity.this);
alert.setTitle("Status Dialog");
alert.setMessage(message);
alert.setIcon(iconId);
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
showActivity(MainMenuActivity.class);
}
});
alert.show();
}
"Can't create handler inside thread that has not called Looper.prepare()" is due to:
Cannot display the Alert dialog in UI thread while running the process in the background thread.
So, place the alert dialog in UI thread in your handleSuccessSaveOrder() as below:
this.runOnUiThread(new Runnable() {
public void run() {
showAlert(Farsi.Convert(" j "),R.drawable.warning);
}
});