I have three strings
String one="Connecting.";
String two="Connecting..";
String three="Connecting...";
I have a textView, what I want is to set text to textview in this order..
one-->two-->three-->one-->two-->three and so on until the process is completed.
I have done it in a for loop based on value i.e
if(value%3==0){
tx.setText(one);
}
else if(value%3==1){
tx.setText(two);
}
else
{
tx.setText(three);
}
This is done inside a thread and it is working well.
But I dont want to rely on "value".. I jst want that until process is completed the text changes in order as mentioned above.
I know it is vague but I am not getting how to do this.
Please if someone can give any hint.
code:
public void startProgress(View view) {
bar.setProgress(0);
tx.setText("Connect");
new Thread(new Task()).start();
}
class Task implements Runnable {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
final int value = i;
try {
Thread.sleep(500);
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
bar.setProgress(value);
String one="Connecting.";
String two="Connecting..";
String three="Connecting...";
if(value%3==0){
tx.setText(one);
}
else if(value%3==1){
tx.setText(two);
}
else
{
tx.setText(three);
}
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
It makes sense to have a counter like value that keeps incrementing. But you could do it a little more simply:
String[] texts = new String[3] {"Connecting.", "Connecting..", "Connecting..."};
int value = 0;
// ...
tx.setText(texts[value]);
value = (value+1)%3;
This way, you don't need your big messy if statement. You will need to find another way of notifying your thread when the job is done, rather than just having a fixed number of iterations.
Use TextSwitcher instead of TextView...It will work
Related
I am replacing my Sqlite database with an online database (Firestore). For that each answer of the database comes back to me by callback.
The problem is that I have several calls to the database in a loop that filled a table and that the table is not accesible unless I declare it in the end and therefore I can not change it.
So I'm looking for a way to fill this table without completely modifying the code that already exists. I saw the ArrayBlockingQueue but I wonder if a simpler solution does not exist.
If possible I would like to keep all the variables inside the function but I have not yet found a solution for that.
I know that for this example we do not necessarily need a table but I want to keep it because it's just an example ;)
Before (SQLite)
public int player_in_x_game(int id_player) {
int gamesWherePlayerIsHere = 0;
ArrayList<Games> gamesArray = Database.getGamesArray();
for (Game game: gamesArray)
if(Utils.isPlayerPresentInGame(game.getId(), idPlayer))
gamesWherePlayerIsHere++;
return gamesWherePlayerIsHere;
}
After (with callbacks)
private static int counter= 0;
private static int resultNP = 0;
private static ArrayBlockingQueue<Integer> results;
public static void numberGamesWherePlayerIsPresent(final long idPlayer, final Callbacks.IntCallback callback){
Thread thread = new Thread() {
#Override
public void run() {
games(new Callbacks.ListGameCallback() {
#Override
public void onCallback(ArrayList<Game> gameArrayList) {
counterNumberGamesWherePlayerIsPresent= gameArrayList.size();
results = new ArrayBlockingQueue<>(gameArrayList.size());
for (Game game: gameArrayList){
Utils.isPlayerPresentInGame(game.getId(), idPlayer, new Callbacks.BooleanCallback() {
#Override
public void onCallback(boolean bool) {
if (bool)
results.add(1);
else
results.add(0);
}
});
}
int result;
try {
while (counter > 0) {
result = results.take();
counter--;
resultNP += result;
}
}catch (InterruptedException ie){
ie.fillInStackTrace();
Log.e(TAG,"results.take() failed");
}
callback.onCallback(resultNP);
}
});
}
};
thread.setName("Firestore - numberGamesWherePlayerIsPresent()");
thread.start();
}
I need to pause and start a line graph in the middle while running.I am using GraphView library. My line graph is showing the graph correctly.I need to implement pause and start from the point where it has paused.How to do that?
Thank you in advance..
I have added my code below.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.fhrlistitemgraph);
String data = getIntent().getExtras().getString("data");
GraphView graph = (GraphView) findViewById(R.id.llgraphview);
series = new LineGraphSeries<DataPoint>();
graph.addSeries(series);
// customize a little bit viewport
Viewport viewport = graph.getViewport();
viewport.setYAxisBoundsManual(true);
viewport.setMinY(0);
viewport.setMaxY(200);
//viewport.setYAxisBoundsManual(true);
viewport.setScalable(true);
viewport.setScrollable(true);
}
#Override
protected void onResume() {
super.onResume();
// we're going to simulate real time with thread that append data to the
// graph
new Thread(new Runnable() {
#Override
public void run() {
String value = null;
String[] data = data.replaceAll("\\[", "").replaceAll(" ", "").replaceAll("\\]", "").split(",");
// we add 100 new entries
for (int i = 0; i < data.length; i++) {
final int j;
j=i;
value = data[i];
final String values;
values = value;
runOnUiThread(new Runnable() {
#Override
public void run() {
addEntry(j,values);
}
});
// sleep to slow down the add of entries
try {
Thread.sleep(600);
} catch (InterruptedException e) {
// manage error ...
}
}
}
}).start();
}
private void addEntry(int i,String value) {
// here, we choose to display max 10 points on the viewport and we
// scroll to end
series.appendData(new DataPoint(i, Integer.valueOf(value)), true, 5);
}
If you stop the thread you've stopped even graph, and when you restart the thread also the graph restart to screen data.
You can use a button in UI to stop the thread.
In a my case, i have insert a boolean to stop the update of graph because the thread was not only that but also other calculations they needed, when the value is true the graph is updated when the value is false the graph is stopped. The value of boolean change whe the button in UI is pressed.
boolean updateGraph = true;
if(updateGraph=true){
series.appendData(new DataPoint(countx++, usedramd), true, 60);
}
And with the button you change the value of boolean updateGraph.
I use a worker thread to read text from a url. My thread is as follow. In the first time running, I am sure thread running is finished as I can check sdcard_readstr is null.
In the second time running, when I call thread_download.start();, then the program crashed.
What could be wrong? Thanks
public class DownloadingThread extends AbstractDataDownloading {
#Override
public void doRun() {
// TODO Auto-generated method stub
try {
// Create a URL for the desired page
URL url = new URL(SDcard_DetailView.textfileurl);
// Read all the text returned by the server
BufferedReader in = new BufferedReader(new
InputStreamReader(url.openStream()));
do{
sdcard_readstr = in.readLine();
}while(sdcard_readstr!=null);
in.close();
} catch (MalformedURLException e) {
} catch (IOException e) {
}
}
}
public abstract class AbstractDataDownloading extends Thread{
private final Set<ThreadCompleteListener> listeners
= new CopyOnWriteArraySet<ThreadCompleteListener>();
public final void addListener(final ThreadCompleteListener listener) {
listeners.add(listener);
}
public final void removeListener(final ThreadCompleteListener listener) {
listeners.remove(listener);
}
private final void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.notifyOfThreadComplete(this);
}
}
#Override
public final void run() {
try {
doRun();
} finally {
notifyListeners();
}
}
public abstract void doRun();
}
EDIT1:
In my thread complete notification, I use runOnUiThreadto use the UI components.
Is that causing problem?
public void notifyOfThreadComplete(Thread thread) {
// TODO Auto-generated method stub
if(downloadingStopbuttonispressed == false){//background process completed
textfileurl = null;
this.runOnUiThread(new Runnable() {
public void run() {
Wifibutton = (Button) findViewById(R.id.Wifiscanning);
Wifibutton.setText("Load another day's data");
final MenuItem refreshItem = optionsMenu.findItem(R.id.airport_menuRefresh);
refreshItem.setActionView(null);
}
});
}
}
I called thread start in onResume() as
#Override
protected void onResume() {
super.onResume();
if(textfileurl != null){
Wifibutton.setText("Stop Data Loading");
buttonStatus = "loading";
setRefreshActionButtonState(true);
thread_download.start();
}
}
EDIT2:
My LogCat image is attached.
My solution is here . I can't reuse the same instance of the Thread object in the second time. I need to create a new instance to call the Thread in the second time. So Thread is suitable for single time running process, for multiple time running process I should use AsyncTask. Even AsyncTack is only for one time execution and for multiple time execution, we should use as new MyAsyncTask().execute(""); I don't understand why people downvote with no reason given. I couldn't find the link in my first search.
I am trying to create a loop that will update a TextView.
The idea is to create some sort of progress indicator, that will increment the
loading precentge.
This is what I have tried, but the result is that I see only the last update of the loop, so I get "100%" with no incremntation.
runOnUiThread(new Runnable() {
public void run() {
final TextView progesss = (TextView)findViewById(R.id.progress);
for(int k=1 ; k<=100; k++)
{
progesss.setText(String.valueOf(k) + "%");
try {
Thread.sleep(15);
} catch(InterruptedException e) {
}
}
}
});
Any ideas of how to achieve my goal?
Thanks!
Your Runnable blocks the UI thread when doing Thread.sleep. Instead of sleeping, you should post a new Runnable again. Try with something like this:
final Handler handler = new Handler();
handler.post( new Runnable(){
private int k = 0;
public void run() {
final TextView progess = (TextView)findViewById(R.id.progress);
progess.setText(String.valueOf(k) + "%");
k++;
if( k <= 100 )
{
// Here `this` refers to the anonymous `Runnable`
handler.postDelayed(this, 15);
}
}
});
That will give the UI thread a chance to run between each call, letting it do its stuff like handling input and drawing stuff on the screen.
You use background thread and UI Thread.
public class testAsync extends AsyncTask<Void, Integer, Voi>{
TextView progress; // You will set TextView referans
protected void doInBackground(){
for(int k=1 ; k<=100; k++)
{
try {
Thread.sleep(1000);
publishProgress(k);
} catch(InterruptedException e) {}
}
}
protected void onProgressUpdate(Integer.. values)
{
progress.setText(values[0]+");
}
}
}
I am implementing AsyncTask for my understanding of concepts. The code is working but not in way I want to. I have gone through the documents but cannot pin point what wrong am I doing.
Code:
private class NewThread extends AsyncTask<Integer, Integer , String>
{
#Override
protected String doInBackground(Integer... params) {
Log.d(TAG,"inside doInBackground");
for (int i=0;i<params.length;i++)
{
try {
publishProgress(i);
Thread.sleep(6000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return "Finished";
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Toast.makeText(getBaseContext(), result, Toast.LENGTH_SHORT).show();
Log.d(TAG,"inside onPostExecute");
}
#Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
Toast.makeText(getBaseContext(), "Done " + values[0], Toast.LENGTH_SHORT).show();
Log.d(TAG,"inside onProgressUpdate");
}
I only see Done 0 and Finished. What I was expecting is Done0 , Finished, Done1, Finished, Done2. Finished.... OR Done0 Done1 Done2 ....Finished.
What should I change in code to do that? Is it even possible?
I am calling AsyncTask using a button.
public void onClick(View v) {
// TODO Auto-generated method stub
new NewThread().execute(4);
}
Thanks
The code you use to start the AsyncTask starts 1 (one) instance, passing 4 as a parameter. Therefore, param.length() is 1 (one) and you get only one output.
Try this instead:
new NewThread().execute(1,2,3,4);
Or maybe this, if you want to see several threads working simultaneously:
new NewThread().execute(1);
new NewThread().execute(2);
new NewThread().execute(3);
Without seeing your code to call the a sync task this is just a guess. Looks like you aren't using the params value quite right. It should be:
for(int i = 0; i < params[0]; i++)
Change this:
#Override
protected String doInBackground(Integer... params) {
Log.d(TAG,"inside doInBackground");
for (int i=0;i<params.length;i++)
to
#Override
protected String doInBackground(Integer myCount) {
Log.d(TAG,"inside doInBackground");
for (int i=0;i<myCount;i++)
Async task is correctly executed. You are passing an array with one item and in the loop you are checking for the lenth of the array which is 1 so you get only one "print".
Either in the loop replace
Also one more minor mistake, you expect done 0, done 1 .. to be printed .
But your statement is "Done " + values[0] , which will always print the same statement :)