So I have this class that downloads stuff... and I am implementing NotificationHelper based on this person's example
private class DatabaseStorageTask extends AsyncTask<String, Integer, String> {
protected String doInBackground(String... params) {
for(int i=0; i<10; i++){
//codes here
downloadFileCount++;
publishProgress( (int) ((downloadFileCount/totalDownloadFileCount) * 100 ) );
}
}
protected void onProgressUpdate(Integer... progress){
Log.e("progressupdate", "in progressupdate");
mNotificationHelper.progressUpdate(progress[0]);
}
}
This is the gist of what goes on in the code. I am unable to see whats causing my problem, as the Notification is constantly displaying 0%, even though I did a Log.e() printing of downloadFileCount and totalDownloadFileCount, which I have checked to be accurate.
Is there something I have missed out to cause the percentage progress not to be updated?
EDIT: Ok so I've placed Log.e() everywhere and I kinda figured out the problem but am not sure of the solution. The percentages and calculates all work fine and are giving the right numbers. However when publishProgress is invoked, the onProgressUpdate is not being called. I do not see the Log.e("progressupdate", "in progressupdate") displayed at all.
maybe it works when
protected String doInBackground(String... params) {
while(downloadFileCount<100){ //try while instead of for-loop
downloadFileCount++;
publishProgress(downloadFileCount); //only count downloadFileCount
}
}
don´t know if it´s the solution, it´s just an idea....
The answer lies in using float rather than int values to get the percentage.
E.g. 5 of 20 = 25%
5/20 = 0.25
when using int = 0
int * 100 = 0
when using float = 0.25
float * 100 = 25
Related
My doubt is will there be a low performance if we perform calculations before setting data in the recycler view in Android?
For example, Im receiving list of data as a server response such as:
Sales target:50 and Sales target achieved:10 for Person A
Sales Target:60 and Sales Target Achieved:15 for Person B,etc..
and I have to show this in a recycler view along with Percentage,
So I do a calculation at Android side to convert these sales target into percentage before setting in the adapter. So before setting the first data, I calculate percentage by doing this: (10/50) *100, which gives me 20%,and so on, for all the list data. So does this calculation lower the performance of loading in Android or will it be better if I calculate the percentage in the server side and get the percentage in the response itself so that I can simply set it without any calculation, but will it affect response time?
So I'm in a confusion between Server Response Time and Android Processing time.
The percentage seems to be not security-sensitive, you could calculate it on client side. If you want to save time on processing the data, try fill some data to the recycler view's adapter to make it visible to user, then perform some asynchronous
background task to calculate the data and update the view.
You should use AsyncTask. It will do task in background thread and will update the UI accordingly.
Below is a simple example:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
To run AsyncTask
new DownloadFilesTask(). execute(param1, param2, param3);
To cancel task call
cancel();
I have a table called student which I want to populate from the server. In my activity I show a progress bar and call ContentProvder.requestSync(Content URI of student..). Now if I understand correctly as per Virgil's talk I should add an observer on the ContentURI of the student to be notified later by the ContentProvider when the sync finishes. But what happens if say there was a network error. The student table will never be populated and my progress dialog will never be removed.
I understand the
"broadcast receiver approach"
mentioned in another thread but that deviates from Virgil's approach which I consider ideal.
Also on those lines why doesn't the requestSync allow to pass a ResultReceiver as part of the extras. Isn't that generally a Service talks back to an Activity?
A SyncAdapter is not meant to be used for this kind of scenario. SyncAdapter is meant for background sync of data, invisible to the user.
Your case sounds like perfect for a AsyncTask. With that you can use publishProgress() to update your progress bar while your network task happens in another thread. You can find a lot of information and examples on AsyncTask online.
Example from the link above:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
run it by executing it like so:
new DownloadFilesTask().execute(url1, url2, url3);
Here is another example, with tutorial (simply found by google):
http://androidresearch.wordpress.com/2012/03/17/understanding-asynctask-once-and-forever/
In this very simple code example, messages get lost every once in a while. What is wrong here?
public class AndroidTesterActivity extends Activity {
private static final int END = 500000;
private static int i = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
i=0;
}
#Override
public void onResume()
{
super.onResume();
while(i < END)
{
Log.d("x", ""+i++);
}
Log.e("x", "END");
}
}
For example i get two consecutive log messages 139371 and 140001 ... so 630 messages are simply lost, even though i is counted up? How can i be counted without the Log being written?
I have already searched, if someone else already had the same problem, but didn't find anything.
Thanks for any help
Just a uneducated guess: The Log class doesn't push everything directly, I think it collects and pushes under some specific conditions. As your loop should go very fast, it might be that in some conditions the log buffer (or what else) might be overwritten before it was flushed.
I would try to make it in a thread and call sleep() with some ms in between. Maybe you can reproduce this or find a value where this behavior disappears.
I have a simple function that counts from 0 to 5000 and does funky math with those numbers, and I would like to display progress bar showing where it is currently counting at (each iteration roughly takes 1 second).
My ProgressBar is the following
<TableRow
android:visibility="gone"
android:id="#+id/progress_bar_row" >
<ProgressBar
android:id="#+id/progress_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content"
android:layout_span="2"
android:layout_height="wrap_content" />
</TableRow>
When user presses button my function starts, it makes the row visible, and I would like to refresh the ProgressBar with each iteration. My function is the following
private void find_number(View v)
{
String response = "";
TextView answer = (TextView)findViewById(R.id.answer);
TableRow progress_bar_row = (TableRow)findViewById(R.id.progress_bar_row);
ProgressBar progress_bar = (ProgressBar)findViewById(R.id.progress_bar);
progress_bar.setProgress(0);
progress_bar.setMax(5000);
progress_bar_row.setVisibility(View.VISIBLE);
answer.setText("");
for(int i = 0; i <= 5000; i++)
{
progress_bar.setProgress(i);
// a lot of heavy math is being performed here and answer is stored inside response string
}
//progress_bar.dismiss();
progress_bar_row.setVisibility(View.GONE);
answer.append(response);
}
I can't seem to figure out a way of going about refreshing the screen. I poked around and got a suggestion to use threads and handlers, I never used threads before, nor would I know how to change my function to adapt to thread use. Or if there is a simpler way without using any threads and simply calling some kind of refresh function I would appreciate it too. Any help or guidance would be very welcome. Thanks in advance
you should use AsyncTask for this problem.
private class YourTask extends AsyncTask<String, Integer, Long> {
protected Long doInBackground(String... strings) {
for(int i = 0; i <= 5000; i++)
{
// your code here
publishProgress((int) ((i / (float) 5000) * 100));
}
return i;
}
protected void onProgressUpdate(Integer... progress) {
progress_bar.setProgress(progress);
}
protected void onPostExecute(Long result) {
//Do something after this task finish
}
}
I have problem that scroll through images on disk which are rather large (about 1 Mb each) Now the problem I have is not the latency between each image but rather that while loading the image the scroll of the image (which I use to signal a change) keeps being detected while the image is loaded resulting in a moved image when it finally loads. My question is simple. Is there a way to wait until the image is loaded (that way I can block screen commands until the image is completely loaded).
Thanks for any answers!
PD: By the way I'm loading the pages in an ImageView;
EDIT:
Posting AsyincCode:
This is in my test activity itests.java
public class ImageLoader extends AsyncTask<String, Void, Void > {
private final ProgressDialog Loading = new ProgressDialog(itests.this);
protected void onPreExecute(){
Loading.setMessage("Loading...");
Loading.show();
}
#Override
protected Void doInBackground(String... params) {
pvm.setPages(params[0], params[1], params[2]);
return null;
}
protected void onPostExecute(Void... params){
if (Loading.isShowing()){
Loading.dismiss();
}
}
Now pvm is my PageViewManager (PageView is my Custom ImageView that receives all my touch events)
Here is what it does:
public void setPages(String left, String center, String right){
//if (!timer.isAlive()){
Left = left;
Center = center;
Right = right;
DoublePageMode = true;
toggleDoublePageMode();
System.err.println("Waiting...");
//centerPage.blockCommands();
//timer.start();
//}
}
#Override
public void toggleDoublePageMode(){
if (DoublePageMode){
//Going into Normal View
threePageLayout.setOrientation(LinearLayout.HORIZONTAL);
leftPage.setVisibility(View.VISIBLE);
LinearLayout.LayoutParams cll = new LinearLayout.LayoutParams(DWidth,DHeight);
LinearLayout.LayoutParams zero = new LinearLayout.LayoutParams(0,DHeight);
centerPage.setImage(Center, DWidth, DHeight, PageState.NORMAL);
centerPage.setLayoutParams(cll);
leftPage.setImage(Left, DWidth, DHeight, PageState.NORMAL);
leftPage.setLayoutParams(zero);
rightPage.setImage(Right, DWidth, DHeight, PageState.NORMAL);
rightPage.setLayoutParams(zero);
DoublePageMode = false;
}
else{
DoublePageMode = true;
threePageLayout.setOrientation(LinearLayout.VERTICAL);
leftPage.setVisibility(View.GONE);
LinearLayout.LayoutParams cll = new LinearLayout.LayoutParams(DWidth,DHeight,1f);
LinearLayout.LayoutParams zero = new LinearLayout.LayoutParams(DWidth,DHeight,1f);
centerPage.setImage(Center, DWidth, DHeight, PageState.TWOPAGEMODE);
centerPage.setLayoutParams(cll);
rightPage.setImage(Right, DWidth, DHeight, PageState.TWOPAGEMODE);
rightPage.setLayoutParams(zero);
}
}
The #Override notation is because the function also has to be called from the PageView on a LongTouch. However I'm not doing any sort of long press so it's not a problem. Since the AsyncTask tries to move the layout of the activity showing the images I get the error I told you, which makes perfect sense.
When I need to call this method It comes from this code (on itests.java):
public void movePages(boolean next) {
//Code that initializes left,center,right
new ImageLoader().execute(left, center, right);
}
This method is called by the PageViewManager (pvm) through an inteface.
I hope this gives you an idea!
Thank you very much!
EDIT2:
I've solved it! Actually more like I found a way around it but I works beautifully!
All I did is create a Timer class that lets me know when a certain time has passed. When I need to load the images I start it (it is another thread) and set a boolean that makes my pages ignore touch events (by returning false in onTouchEvent). When it is done it call a function in my pvm that simply set that boolean again to true and the effect is just what I wanted. The timer waits for only about 500 miliseconds.
Thanks for all the help!
I hope your using a aSyncTask to load the data! You could simply add a progress dialog whilst loading the data. this can be done by adding:
pDialog = ProgressDialog.show(this, "Loading Data", "Please Wait...", true);
before you start loading the data, then once all your data is ready simply call pDialog.dismiss();
One (longish) solution I can think of is to implement your own ImageView class, which loads a BitmapDrawable and draws it in onDraw(). This way, you can know for sure when onDraw() completes, and call a different callback (e.g. onDrawComplete() ) to toggle touch event handling.