I am making a project in which i am using the progressdialog and i want to show this progress dialog on creation of activity and i am able to that. In the on create method i want the image to be invisible and i want image to be visible after completion of progress dialog but it is throwing exception in the line imagevisible();
The logcat is:
04-12 12:48:35.309: E/AndroidRuntime(4994): at com.example.project1.ShowPassword$waiter.run(ShowPassword.java:59)
Code
ImageView iv;
ProgressDialog p;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.showpass);
iv=(ImageView)findViewById(R.id.imageView1);
iv.setVisibility(View.INVISIBLE);
p= new ProgressDialog(this);
p.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
p.setTitle("Getting Password: ");
p.setMessage("Loading:");
p.setMax(100);
p.show();
Thread t=new Thread(new waiter());
t.start();
public class waiter extends Thread{
public void run(){
for(int i=0; i<5; i++){
p.incrementProgressBy(20);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}p.dismiss();
imagevisible();
}
}
public void imagevisible(){
iv.setVisibility(View.VISIBLE);
}
You can't change UI from non UI thread. You can use runOnUiThread method of Activity:
public class waiter extends Thread{
public void run(){
//...
runOnUiThread(new Runnable() {
#Override
public void run() {
imagevisible();
}
});
}
}
What you want is an AsyncTask. Implement doInBackground() (runs in the background) and onPostExecute() (runs on the UI thread).
https://developer.android.com/reference/android/os/AsyncTask.html
Related
Android recommend update ui in the ui thread,but i found that i can update the ui in the non-ui thread directly like below:
public class MainActivity extends Activity {
private TextView textView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.text);
new Thread(new Runnable() {
#Override
public void run() {
textView.setText("SecondThread");
}
}).start();
}
}
That's run correctly,but if i sleep the thread 1000ms:
public class MainActivity extends Activity {
private TextView textView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.text);
new Thread(new Runnable() {
#Override
public void run() {
try {
**Thread.sleep(1000);**
} catch (InterruptedException e) {
e.printStackTrace();
}
textView.setText("SecondThread");
}
}).start();
}
}
I get the error"Only the original thread that created a view hierarchy can touch its views",i try to change the sleep value much times,i found when i set the value 135 or less,it can run correctly:
Thread.sleep(135);
Thread.sleep(134);
Thread.sleep(...);
That's very interesting!But why it happen?I can't find any way to make sense of that,is anyone can help me?thanks!
If you are trying to touch views from background thread you should consider using runOnUiThread method, which accepts runnable as argument in which you can update views
EDIT: Also I would recommed you to use AsyncTask to achieve your goals, it has two callbacks onPreExecute and onPostExecute, whiche are invoked on the UI thread
so will always work
new Thread(new Runnable() {
#Override
public void run() {
try {
**Thread.sleep(1000);**
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runable(){
#Override
public void run(){
textView.setText("SecondThread");
});
}
}).start();
There is another way to use the Handler()
I have a SetContentView(R.layout.camera);
I want this layout to be start executing after some milliseconds....till then it should be blank. How can I achieve this in android?
For this Write your onCreate() like this..Then it will work..
Thread t = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
t = new Thread(new Runnable() {
#Override
public void run() {
try {
t.sleep(5000);
runOnUiThread(new Runnable() {
public void run() {
setContentView(R.layout.activity_main);
}
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t.start();
}
you can use handler for make delay
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
//setcontentview
}
};
in oncreate methode
Message m = Message.obtainMessage();
handler.sendMessageDelayed(m, delayMillis);
Your activity will not be visible unless onResume() will get called, Do some operation in main Thread or onCreate() Method it will block your main thread and UI will not be displayed until your operation gets completed.
Create root View with all the components and visibility set to INVISIBLE or GONE and then show it after delay. You can use Handler and postDelayed to execute a code after delay.
I am working on an android app in which i want to hide my image view after some interval. i am using this code but it is not hiding. can anybody tell me how i can hide it ???
showtrue1.setBackgroundResource(R.drawable.ticktrue);
showtrue1.setVisibility(View.VISIBLE);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
showtrue1.setVisibility(View.GONE);
Try CountDownTimer:
new CountDownTimer(1000, 100) {
public void onTick(long millisUntilFinished) {
// implement whatever you want for every tick
}
public void onFinish() {
showtrue1.setVisibility(View.GONE);
}
}.start();
You can use async Task also to solve your problem . In its backgound function make a thread sleep for particular second and in the post method make trhe visibility gone for your image viiew.
Call the execute method in your oncreate
new MyAsyncTask().execute();
and make an inner class as defined below:
private class MyAsyncTask extends AsyncTask<Void, Void, Void>{
#Override
protected void onPreExecute(){
// show your progress dialog
showtrue1.setBackgroundResource(R.drawable.ticktrue);
showtrue1.setVisibility(View.VISIBLE);
}
#Override
protected Void doInBackground(Void... voids){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void params)
{
showtrue1.setVisibility(View.GONE);
}
}
Create a separate thread that sleeps for 1 seconds then call runOnUiThread to hide the view.
Thread thread = new Thread() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
runOnUiThread(new Runnable() {
#Override
public void run() {
// Do some stuff
showtrue1.setVisibility(View.GONE);
}
});
}
};
I'm coding a program which fetches the data from MySql from server (using JSON) and it updates the UI accordingly,
I'm fetching two types of data using AsyncTask from Server
1) Bubble Answers
2) Comments
The parseBubbleAnswers method successfully runs and Updates UI,
but parseComments class which is AsyncTask, and which call parseComments method in doInBackground, is not running runOnUiThread(new Runnable() { run() });
Can anyone help me in solving this
Here is my code :
public class FetchServer extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
String photoId = "1"; // photo id for which the data is fetched
checkBubbleData(photoId); // which call AsyncTask - 2 differnt calls
}
public void checkBubbleData(String photoId)
{
new parseBubbleAnswers().execute(photoId); // to fetch bubble answers
new parseComments().execute(photoId); // to fetch comments
}
class parseBubbleAnswers extends AsyncTask<String, Integer,String>
{
#Override
protected String doInBackground(String... params)
{
// TODO Auto-generated method stub
Looper.prepare();
parseBubbleAnswers(); // which has runOnUiThread(new Runnable() which updates (successfully !) the UI
return null;
}
}
class parseComments extends AsyncTask<String, Integer,String>
{
#Override
protected String doInBackground(String... params)
{
// TODO Auto-generated method stub
Looper.prepare();
String parseComReturn = parseComments();
if(parseComReturn=="end")
{
commentBuilder(); // which will update UI after fetch data by parseComments() method
}
}
}
public void commentBuilder()
{
runOnUiThread(new Runnable() // while debugging, it comes here, on Step Over it stick for 2 times and then move at the end of method without error
{
public void run()
{
// update UI code
}
});
}
}
Try this way :
First create one Handler :
Handler mHandler = new Handler();
Change this,
public void commentBuilder()
{
runOnUiThread(new Runnable() // while debugging, it comes here, on Step Over it stick for 2 times and then move at the end of method without error
{
public void run()
{
// update UI code
}
});
}
With,
public void commentBuilder()
{
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (isRunning) {
try {
// Thread.sleep(10000);
mHandler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
// Write your code here to update the UI.
}
});
} catch (Exception e) {
// TODO: handle exception
}
}
}
}).start();
}
Stop thread by this once you are done with UI,
isRunning = false;
EDIT :
Try to Use Async Task in this way :
class parseComments extends AsyncTask<String, Integer,String>
{
protected String doInBackground(String... params) {
String parseComReturn = parseComments();
return parseComReturn;
}
protected void onPostExecute(String result) {
if(result.equals("end"))
{
commentBuilder();
}
}
}
Thanks.
runOnUiThread is a method of Activity, AsyncTask has no reference to Activity.
however, AsyncTask already runs on the UI thread and was designed to do exactly that.
just deal with the UI changes in onPostExecute.
I faced the similar issue.
Just pass the reference of the Activity class to the parseComments class.
class parseComments extends AsyncTask<String, Integer,String>{
Activity activity;
public parseComments(Activity activity){
this.activity = activity;
}
}
After that you can use runOnUiThread as
activity.runOnUiThread(new Runnable(){
#Override
public void run(){
}
});
It will only work with Activity class. Not Context class.
I want show dialog after finish Thread.
In thread I am changing TextView's Value like as 0 to 100...
When TextView Value is reach 100 then i want to show dialog..
What i do for it.
Thanks in advance...
Code Snippet:
final Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
synchronized (this)
{
try
{
for(int i=0 ; i<speed; i++)
{
final int value=i+1;
wait(3000/speed);
Test.this.runOnUiThread(new Runnable() {#Override public void run()
{
accText.setText(String.valueOf(value));
}});
}
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
thread.start();
this is asyntask code snippet...
class setTextBackgroundTask extends AsyncTask<String , Integer, Void>
{
#Override
protected void onPreExecute()
{
}
#Override
protected Void doInBackground(String... params)
{
Thread th = new Thread();
int value;
for(int i=0 ; i<speed; i++)
{
value=i+1;
publishProgress(value);
try {
th.sleep(3000/speed);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values)
{
accText.setText(String.valueOf(values[0]));
System.out.println("Value=="+values[0]);
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Void result)
{
showShareDialog();
}
}
This document explains how you can create dialogs.
Please note that you will have to do any dialog creation code on the UI thread.
You already have code that runs something on the UI thread, just do that outside the loop,but with the dialog creation code inside.
You should use AsyncTask: subclass AsyncTask, override doInBackground() to execute your time consuming action on another thread, and then override onPostExecute() to show your dialog.
Note that you cannot change UI elements from a non-UI (background) thread. AsyncTask takes care of that for you: it calls doInBackground() on a new thread and then calls onPostExecute() on the UI thread as soon as the background task is complete.