Android ListViewItem update Progressbar in row - java

I'm using ListView with custom list rows,where every ListItem has ProgressBar in it.
When the user click the ImageView,the app starts an AsyncTask to download a file from a remote server,and update the progress in progress bar.
I'm using Parallel async tasks,which mean app can launch multiple downloads and update them in the ProgressBar of each row.
This is the code
static class ViewHolder {
protected TextView title;
protected TextView size;
protected TextView version;
protected ImageView appIcon;
protected ProgressBar progressBar;
}
public class UpdateAdapter extends ArrayAdapter<UpdateItem> {
public UpdateAdapter(Context context, ArrayList<UpdateItem> users) {
super(context, 0, users);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
UpdateItem updateItem = getItem(position);
View v = convertView;
ViewHolder viewHolder;
LayoutInflater mInflater = LayoutInflater.from(getContext());
if (convertView == null) { // if convertView is null
convertView = mInflater.inflate(R.layout.row, null);
viewHolder = new ViewHolder();
viewHolder.title = (TextView) convertView.findViewById(R.id.apptitlelabel);
viewHolder.version = (TextView) convertView.findViewById(R.id.versionlabel);
viewHolder.size = (TextView) convertView.findViewById(R.id.sizelabel);
viewHolder.appIcon = (ImageView) convertView.findViewById(R.id.appicon);
viewHolder.progressBar = (ProgressBar) convertView.findViewById(R.id.downloadProgressBar);
convertView.setTag(viewHolder);
} else
viewHolder = (ViewHolder) v.getTag();
viewHolder.progressBar.setProgress(0);
View finalConvertView = convertView;
viewHolder.appIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DownloadFileFromURL task = new DownloadFileFromURL();
task.position = position;
task.v = finalConvertView;
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, updateItem.downloadlink);
}
});
return convertView;
}
class DownloadFileFromURL extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Bar Dialog
**/
int position;
View v;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
/**
* Downloading file in background thread
**/
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// this will be useful so that you can show a tipical 0-100%
// progress bar
int lenghtOfFile = conection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream(),
8192);
// Output stream
String fileExtenstion = MimeTypeMap.getFileExtensionFromUrl(url.getPath());
String fname = URLUtil.guessFileName(url.getPath(), null, fileExtenstion);
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().toString() + "/" + fname);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
/**
* Updating progress bar
**/
protected void onProgressUpdate(String... progress) {
// setting progress percentage
// Log.w(TAG, progress[0]);
updateStatus(position, Integer.parseInt(progress[0]));
}
/**
* After completing background task Dismiss the progress dialog
**/
#Override
protected void onPostExecute(String file_url) {
// dismiss the dialog after the file was downloaded
Log.w(TAG, "onPostExecute: ");
removeListItem(v, position);
}
}
public void updateStatus(int index, int Status) {
int in = index - updateLv.getFirstVisiblePosition();
View v = updateLv.getChildAt(in);
ProgressBar progress = (ProgressBar) v.findViewById(R.id.downloadProgressBar);
progress.setProgress(Status);
}
The problem is ,when the user starts two downloads(say hit the first the second imageviews),and the first task has been completed,and the first row getting removed from the list,in onPostExecute,now,the second row turns into the first row,but the task updates the current second row(which was the third before the first item removed...)
I know it happens because I pass into updateStatus,the position of the item to be updated,but in the meantime the ListView Changes and removes items(because their download has been completed),but I have no current solution for this...
I even tried passing a ProgressBar object reference to updateStatus method ,instead of using item position,and I thought it would solve the problem...but no luck :)

Related

How to add image depending on what result or emotion it might detect

I have been trying to figure this out all day, as I would like to add an image depending on the outcome of the emotion may detect. Just wanted to add some some images but I'm still new to this. Can anyone help me with this one to.
btw here's my code:
public class DetectionActivity extends AppCompatActivity {
// Background task of face detection.
private class DetectionTask extends AsyncTask<InputStream, String, Face[]> {
private boolean mSucceed = true;
#Override
protected Face[] doInBackground(InputStream... params) {
// Get an instance of face service client to detect faces in image.
FaceServiceClient faceServiceClient = SampleApp.getFaceServiceClient();
try {
publishProgress("Detecting...");
// Start detection.
return faceServiceClient.detect(
params[0], /* Input stream of image to detect */
true, /* Whether to return face ID */
true, /* Whether to return face landmarks */
new FaceServiceClient.FaceAttributeType[]{
FaceServiceClient.FaceAttributeType.Emotion,
});
} catch (Exception e) {
mSucceed = false;
publishProgress(e.getMessage());
addLog(e.getMessage());
return null;
}
}
#Override
protected void onPreExecute() {
mProgressDialog.show();
addLog("Request: Detecting in image " + mImageUri);
}
#Override
protected void onProgressUpdate(String... progress) {
mProgressDialog.setMessage(progress[0]);
setInfo(progress[0]);
}
#Override
protected void onPostExecute(Face[] result) {
if (mSucceed) {
addLog("Response: Success. Detected " + (result == null ? 0 : result.length)
+ " face(s) in " + mImageUri);
}
// Show the result on screen when detection is done.
setUiAfterDetection(result, mSucceed);
}
}
// Flag to indicate which task is to be performed.
private static final int REQUEST_SELECT_IMAGE = 0;
// The URI of the image selected to detect.
private Uri mImageUri;
// The image selected to detect.
private Bitmap mBitmap;
// Progress dialog popped up when communicating with server.
ProgressDialog mProgressDialog;
// When the activity is created, set all the member variables to initial state.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detection);
//this hides the back button and I thank you
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setTitle(getString(R.string.progress_dialog_title));
// Disable button "detect" as the image to detect is not selected.
setDetectButtonEnabledStatus(false);
LogHelper.clearDetectionLog();
}
// Save the activity state when it's going to stop.
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("ImageUri", mImageUri);
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case R.id.menuAbout:
// Toast.makeText(this, "You clicked about", Toast.LENGTH_SHORT).show();
View messageView = getLayoutInflater().inflate(R.layout.about, null, false);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.drawable.smile);
builder.setTitle(R.string.app_name);
builder.setView(messageView);
builder.create();
builder.show();
break;
case R.id.menuHelp:
// Toast.makeText(this, "You clicked settings", Toast.LENGTH_SHORT).show();
// Intent help = new Intent(this, HelpActivity.class);
//startActivity(help);
// break;
View messageViewh = getLayoutInflater().inflate(R.layout.help, null, false);
AlertDialog.Builder builderh = new AlertDialog.Builder(this);
builderh.setIcon(R.drawable.smile);
builderh.setTitle(R.string.app_nameh);
builderh.setView(messageViewh);
builderh.create();
builderh.show();
break;
}
return true;
}
// Recover the saved state when the activity is recreated.
#Override
protected void onRestoreInstanceState(#NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mImageUri = savedInstanceState.getParcelable("ImageUri");
if (mImageUri != null) {
mBitmap = ImageHelper.loadSizeLimitedBitmapFromUri(
mImageUri, getContentResolver());
}
}
// Called when image selection is done.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_SELECT_IMAGE:
if (resultCode == RESULT_OK) {
// If image is selected successfully, set the image URI and bitmap.
mImageUri = data.getData();
mBitmap = ImageHelper.loadSizeLimitedBitmapFromUri(
mImageUri, getContentResolver());
if (mBitmap != null) {
// Show the image on screen.
ImageView imageView = (ImageView) findViewById(R.id.image);
imageView.setImageBitmap(mBitmap);
// Add detection log.
addLog("Image: " + mImageUri + " resized to " + mBitmap.getWidth()
+ "x" + mBitmap.getHeight());
}
// Clear the detection result.
FaceListAdapter faceListAdapter = new FaceListAdapter(null);
ListView listView = (ListView) findViewById(R.id.list_detected_faces);
listView.setAdapter(faceListAdapter);
// Clear the information panel.
setInfo("");
// Enable button "detect" as the image is selected and not detected.
setDetectButtonEnabledStatus(true);
}
break;
default:
break;
}
}
// Called when the "Select Image" button is clicked.
public void selectImage(View view) {
Intent intent = new Intent(this, SelectImageActivity.class);
startActivityForResult(intent, REQUEST_SELECT_IMAGE);
}
// Called when the "Detect" button is clicked.
public void detect(View view) {
// Put the image into an input stream for detection.
ByteArrayOutputStream output = new ByteArrayOutputStream();
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
ByteArrayInputStream inputStream = new ByteArrayInputStream(output.toByteArray());
// Start a background task to detect faces in the image.
new DetectionTask().execute(inputStream);
// Prevent button click during detecting.
setAllButtonsEnabledStatus(false);
}
// View the log of service calls.
public void viewLog(View view) {
Intent intent = new Intent(this, DetectionLogActivity.class);
startActivity(intent);
}
// Show the result on screen when detection is done.
private void setUiAfterDetection(Face[] result, boolean succeed) {
// Detection is done, hide the progress dialog.
mProgressDialog.dismiss();
// Enable all the buttons.
setAllButtonsEnabledStatus(true);
// Disable button "detect" as the image has already been detected.
setDetectButtonEnabledStatus(false);
if (succeed) {
// The information about the detection result.
String detectionResult;
if (result != null) {
detectionResult = result.length + " face"
+ (result.length != 1 ? "s" : "") + " detected";
// Show the detected faces on original image.
ImageView imageView = (ImageView) findViewById(R.id.image);
imageView.setImageBitmap(ImageHelper.drawFaceRectanglesOnBitmap(
mBitmap, result, true));
// Set the adapter of the ListView which contains the details of the detected faces.
FaceListAdapter faceListAdapter = new FaceListAdapter(result);
// Show the detailed list of detected faces.
ListView listView = (ListView) findViewById(R.id.list_detected_faces);
listView.setAdapter(faceListAdapter);
} else {
detectionResult = "0 face detected";
}
setInfo(detectionResult);
}
mImageUri = null;
mBitmap = null;
}
// Set whether the buttons are enabled.
private void setDetectButtonEnabledStatus(boolean isEnabled) {
Button detectButton = (Button) findViewById(R.id.detect);
detectButton.setEnabled(isEnabled);
}
// Set whether the buttons are enabled.
private void setAllButtonsEnabledStatus(boolean isEnabled) {
Button selectImageButton = (Button) findViewById(R.id.select_image);
selectImageButton.setEnabled(isEnabled);
Button detectButton = (Button) findViewById(R.id.detect);
detectButton.setEnabled(isEnabled);
// Button ViewLogButton = (Button) findViewById(R.id.view_log);
// ViewLogButton.setEnabled(isEnabled);
}
// Set the information panel on screen.
private void setInfo(String info) {
TextView textView = (TextView) findViewById(R.id.info);
textView.setText(info);
}
// Add a log item.
private void addLog(String log) {
LogHelper.addDetectionLog(log);
}
// The adapter of the GridView which contains the details of the detected faces.
private class FaceListAdapter extends BaseAdapter {
// The detected faces.
List<Face> faces;
// The thumbnails of detected faces.
List<Bitmap> faceThumbnails;
// Initialize with detection result.
FaceListAdapter(Face[] detectionResult) {
faces = new ArrayList<>();
faceThumbnails = new ArrayList<>();
if (detectionResult != null) {
faces = Arrays.asList(detectionResult);
for (Face face : faces) {
try {
// Crop face thumbnail with five main landmarks drawn from original image.
faceThumbnails.add(ImageHelper.generateFaceThumbnail(
mBitmap, face.faceRectangle));
} catch (IOException e) {
// Show the exception when generating face thumbnail fails.
setInfo(e.getMessage());
}
}
}
}
#Override
public boolean isEnabled(int position) {
return false;
}
#Override
public int getCount() {
return faces.size();
}
#Override
public Object getItem(int position) {
return faces.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater layoutInflater =
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.item_face_with_description, parent, false);
}
convertView.setId(position);
// Show the face thumbnail.
((ImageView) convertView.findViewById(R.id.face_thumbnail)).setImageBitmap(
faceThumbnails.get(position));
// Show the face details.
String getEmotion;
// String improve = improveMessage(getEmotion);
DecimalFormat formatter = new DecimalFormat("#0.0");
//add
// String message = findMessage(getEmotion());
// String improve = improveMessage(getEmotion);
String face_description = String.format("Emotion: %s\n",
getEmotion(faces.get(position).faceAttributes.emotion)
);
((TextView) convertView.findViewById(R.id.text_detected_face)).setText(face_description);
return convertView;
}
private String getEmotion(Emotion emotion) {
String emotionType = "";
double emotionValue = 0.0;
String emotionInfo = "";
if (emotion.anger > emotionValue) {
emotionValue = emotion.anger;
emotionType = "Anger";
emotionInfo = "If you haven't fed him/her yet maybe this precious one is thirsty or hungry.\n Try giving your attention. If your baby is acting unusual it's best to seek for medical help.";
}
if (emotion.contempt > emotionValue) {
emotionValue = emotion.contempt;
emotionType = "Contempt";
emotionInfo = "You go girl!";
}
if (emotion.disgust > emotionValue) {
emotionValue = emotion.disgust;
emotionType = "Disgust";
emotionInfo = "Look! If your baby is feeling this way mabye she/he doesn't like this. \n If what your doing right now is good for him/her maybe you can support that.";
}
if (emotion.fear > emotionValue) {
emotionValue = emotion.fear;
emotionType = "Fear";
emotionInfo = "Your baby looks somewhat uncomfortable.\n Make your baby feel comfortable and take note of what makes them feel like that. ";
}
if (emotion.happiness > emotionValue) {
emotionValue = emotion.happiness;
emotionType = "Happiness";
emotionInfo = "Just continue what you are doing. It is important to remember what can make them happy. \n";
}
if (emotion.neutral > emotionValue) {
emotionValue = emotion.neutral;
emotionType = "Neutral";
emotionInfo = "Maybe you should just observe first";
}
if (emotion.sadness > emotionValue) {
emotionValue = emotion.sadness;
emotionType = "Sadness";
emotionInfo = "Just cuddle or dandle your baby.";
}
if (emotion.surprise > emotionValue) {
emotionValue = emotion.surprise;
emotionType = "Surprise";
emotionInfo = "Oooh look. Play with your baby. Try doing peek a boo";
}
return String.format("%s: %f \n\n%s", emotionType, emotionValue, emotionInfo);
}
}
}
Just would like to add some images like happy if that is the detected emotion. Please do help me. Any help is highly appreciated. Thank you :)
I would like to add that after the emotionInfo.
I guess detectWithStream is you want.
Official Doc: Faces.detectWithStream Method
From Java SDK, the List<DetectedFace> object will return if successful.

Downloading images and text from Parse and adding to ArrayList provides unexpected result?

I've been working on an app that downloads thumbnails and text from Parse and adds it to ArrayLists which are then displayed through a custom adapter for a ListView. The issue here is, the thumbnails for the required content is sometimes misplaced. For example: In my profile, instead of my pic another pic downloaded from parse would be placed. How to fix it ?
MainActivity.java ( Downloads the content )
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (isParseInitialized == false) {
Parse.initialize(new Parse.Configuration.Builder(this)
.applicationId("AppId")
.clientKey("ClientKey")
.server("https://parseapi.back4app.com")
.build()
);
isParseInitialized = true;
}
catchVideos();
progressBar = (ProgressBar) findViewById(R.id.progressBar);
context = this;
listView = (ListView) findViewById(R.id.listView);
customAdapter = new CustomAdapter(MainActivity.this, titles, thumbnails, channel);
//progressBar.setVisibility(View.INVISIBLE);
final Handler handler = new Handler();
Runnable run = new Runnable() {
#Override
public void run() {
handler.postDelayed(this, 1000);
if (tapped == true) {
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("Content");
query.whereEqualTo("Title", title);
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if(e == null) {
for (ParseObject object : objects) {
Log.i("Info", object.getString("url"));
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(object.getString("url")));
startActivity(intent);
}
}
}
});
tapped = false;
}
}
};
handler.post(run);
}
public void catchVideos(){
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("Content");
query.whereNotEqualTo("Status", null);
query.orderByDescending("createdAt");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if(e == null) {
if (!titles.isEmpty()) {
titles.clear();
}
if (!channel.isEmpty()) {
channel.clear();
}
if (!thumbnails.isEmpty()) {
thumbnails.clear();
}
for (ParseObject object : objects) {
titles.add(object.getString("Title"));
channel.add(object.getString("Channel"));
ParseFile file = (ParseFile) object.get("Thumbnail");
file.getDataInBackground(new GetDataCallback() {
#Override
public void done(byte[] data, ParseException e) {
if (e == null) {
Bitmap thumbnail = BitmapFactory.decodeByteArray(data, 0, data.length);
thumbnails.add(thumbnail);
listView.setAdapter(customAdapter);
progressBar.setVisibility(View.INVISIBLE);
}
}
});
customAdapter.notifyDataSetChanged();
Log.i("Info", object.getString("Title"));
Log.i("Info", object.getString("url"));
}
}
}
});
}
CustomAdapter.java
public class CustomAdapter extends BaseAdapter{
ArrayList<String> result;
ArrayList<String> channelName;
Context context;
ArrayList<Bitmap> imageId;
private static LayoutInflater inflater=null;
public CustomAdapter(MainActivity mainActivity, ArrayList<String> titles, ArrayList<Bitmap> thumbnails, ArrayList<String> channel) {
// TODO Auto-generated constructor stub
result=titles;
channelName=channel;
context=mainActivity;
imageId=thumbnails;
inflater = ( LayoutInflater )context.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return result.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public class Holder
{
TextView tv;
TextView channelText;
ImageView img;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Holder holder=new Holder();
View rowView;
rowView = inflater.inflate(R.layout.custom_row, null);
holder.tv=(TextView) rowView.findViewById(R.id.textView1);
holder.channelText = (TextView) rowView.findViewById(R.id.channel);
holder.img=(ImageView) rowView.findViewById(R.id.imageView1);
try {
holder.img.setImageBitmap(imageId.get(position));
} catch (Exception e) {
e.printStackTrace();
}
holder.tv.setText(result.get(position));
holder.channelText.setText(channelName.get(position));
rowView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//Toast.makeText(context, "You Clicked "+ result.get(position), Toast.LENGTH_LONG).show();
//Launch URL
MainActivity.tapped = true;
MainActivity.title = result.get(position);
}
});
return rowView;
}
}
You're adding each image to a list once it is downloaded. Later, you're iterating over the images in order. However, the order that they appear in the list won't necessarily be the same as the order you requested them. They're being loaded asynchronously, meaning that the code doesn't wait for the image to finish loading before moving on to the next one. If you start loading a large image and then start loading a small image immediately afterwards, the small one might finish downloading first. In the resulting list, the small image would appear before the larger one, even though it was requested second.
To fix the order of the list of images, you could use Futures. Instead of declaring thumbnails as a List<Bitmap>, make it a List<Future<Bitmap>>. Then, add all three items to the list at the same time.
titles.add(object.getString("Title"));
channel.add(object.getString("Channel"));
CompletableFuture<Bitmap> futureThumbnail = new CompletableFuture<>();
thumbnails.add(futureThumbnail);
That guarantees all three lists will be in the same order, regardless of how long the images take to download.
The next step is to fill in each future with the corresponding image.
ParseFile file = (ParseFile) object.get("Thumbnail");
file.getDataInBackground(new GetDataCallback() {
#Override
public void done(byte[] data, ParseException e) {
if (e == null) {
Bitmap thumbnail = BitmapFactory.decodeByteArray(data, 0, data.length);
future.complete(thumbnail);
...
This method has the added benefit that you can wait for the images to finish downloading. To wait for all the images to download and put them in a list in the right order:
List<Bitmap> thumbnails = new ArrayList<>();
for (Future<Bitmap> future : futureThumbnails) {
thumbnails.add(future.get());
}
Or, if you prefer not to wait:
List<Bitmap> thumbnails = new ArrayList<>();
Bitmap defaultValue = null; // or preferably some other default value
for (Future<Bitmap> future : futureThumbnails) {
thumbnails.add(future.isDone() ? future.get() : defaultValue);
}

ProgressBar - Not Updating in AsyncTask

Hi just had a quick question about why my progressbar isn't updating. I will add comments in the below to demonstrate what is working and what isn't.
To my knowledge it should be working since it updates in an asynctask.
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if (!(data.get(position) instanceof TemporarySongInfomation)) {
SongViewHolder holder;
view = inflater.inflate(R.layout.music_list_format, null);
holder = new SongViewHolder();
holder.timesplayed = (TextView) view.findViewById(R.id.textView7);
holder.artist = (TextView) view.findViewById(R.id.textView6);
holder.title = (TextView) view.findViewById(R.id.textView5);
holder.imagebutton = (ImageButton) view.findViewById(R.id.playbutton);
holder.source = (TextView) view.findViewById(R.id.textView8);
tempValue = (SongInfomation) data.get(position);
String songName = tempValue.getName();
holder.imagebutton.setBackgroundResource(R.drawable.playbutton1);
holder.source.setText(tempValue.getVideoid());
holder.title.setText(songName.length() > 45 ? songName.substring(0, 38) + "..." : songName);
holder.timesplayed.setText("" + tempValue.getTimesplayed());
holder.artist.setText(tempValue.getArtist());
swipeDetector = new SwipeDetector();
view.setOnClickListener(new SongListOnItemClickListener(position));
view.setOnTouchListener(swipeDetector);
holder.imagebutton.setOnClickListener(new OnPlayButtonClickListener(position));
} else {
TemporarySongViewHolder holder;
view = inflater.inflate(R.layout.music_list_process_format, null);
holder = new TemporarySongViewHolder();
holder.artist = (TextView) view.findViewById(R.id.artisttemp);
holder.bar = (ProgressBar) view.findViewById(R.id.ppbar);
holder.title = (TextView) view.findViewById(R.id.titletemp);
holder.source = (TextView) view.findViewById(R.id.sourcetemp);
tempValue1 = (TemporarySongInfomation) data.get(position);
String songName = tempValue1.getName();
holder.source.setText(tempValue1.getVideoid());
holder.title.setText(songName.length() > 45 ? songName.substring(0, 38) + "..." : songName);
holder.artist.setText(tempValue1.getArtist());
holder.bar.setMax(100);
// the below line starts the task!
new UpdateProgressBar(holder.bar, tempValue1).execute();
}
return view;
}
private class UpdateProgressBar extends AsyncTask<Void, Void, Void> {
private TemporarySongInfomation songinfo;
private ProgressBar progress;
UpdateProgressBar(ProgressBar bar, TemporarySongInfomation tp) {
progress = bar;
songinfo = tp;
}
#Override
protected Void doInBackground(Void... params) {
while (!songinfo.isCompleted()) {
System.out.println("going " + (int) songinfo.getProgress());
// the above line prints different values for songinfo.getProgress()
progress.setProgress((int) songinfo.getProgress());
publishProgress();
System.out.println("Progress "+progress.getProgress());
// the above line only prints "Progress 0"
// and obviously the ui doesnt update.
try {
Thread.sleep(500);
} catch (Exception e) {
}
}
return null;
}
}
publishProgress(Progress...) calls onProgressUpdate(Progress...)
onProgressUpdate(Progress...) invoked on the UI thread after a call to
publishProgress(Progress...). The timing of the execution is
undefined. This method is used to display any form of progress in the
user interface while the background computation is still executing.
For instance, it can be used to animate a progress bar or show logs in
a text field.
so basically you need to update the UI thread from onProgressUpdate method.
Here an 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");
}
}
This part is wrong
progress.setProgress((int) songinfo.getProgress());
publishProgress();
You need to update the progress bar from the UI thread. So to update progress, you must override onProgressUpdate, which is run on the UI thread, and update your progress bar from there.
in doInBackground, do this
publishProgress((int) songinfo.getProgress()); // this calls onProgressUpdate on the UI thread
then, in onProgressUpdate, do this
progress.setProgress(values[0]); // called on UI thread
You will also need to change your AsyncTask class definition
private class UpdateProgressBar extends AsyncTask<Void, Integer, Void> { // Integer progress type

How can I avoid calling of getView() method of adapter class when I tap on listitems?

I have implemented list view having buttons having background image changing effects.but, when I tap on any list item, that effect is no longer present there and get refreshed.
I checked that, when I tap on any list item, that getView() is calling...
How to avoid this???
please suggest any solution if anyone knows...
Thank you..
code is :
public class EventListAdapter extends BaseAdapter {
private static final int VISIBLE = 0;
private static final int GONE = 8;
private List<Events> dateForEventList;
private String eventsRetrived;
private String[] events;
boolean clickStatus = false;
private int status = 0;
public EventListAdapter(Context context)
{
mContext = context;
}
/**
* The number of items in the list is determined by the number of announcements
* in our array.
*
* #see android.widget.ListAdapter#getCount()
*/
public int getCount() {
DatabaseManager db = new DatabaseManager(mContext);
dateForEventList = db.getAllData1(CalendarAdapter.dateOfEventSingle);
for (Events l : dateForEventList) {
eventsRetrived = l.getEventData();
}
events = eventsRetrived.split(",");
return events.length;
}
/**
* Since the data comes from an array, just returning
* the index is sufficent to get at the data. If we
* were using a more complex data structure, we
* would return whatever object represents one
* row in the list.
*
* #see android.widget.ListAdapter#getItem(int)
*/
public Object getItem(int position) {
return position;
}
/**
* Use the array index as a unique id.
* #see android.widget.ListAdapter#getItemId(int)
*/
public long getItemId(int position) {
return position;
}
public View getView(final int position, View myView, ViewGroup parent) {
if(myView == null) {
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
myView = inflater.inflate(R.layout.activity_event_list, null);
}
TextView textViewTitle;
TextView textViewDialogue;
final ImageButton buttonForCheckMark;
final ImageButton buttonForDelete;
final ImageButton buttonForRemainder;
//Events event = new Events("11/2/2013","today, there is function in Shivajinagar");
// event.setDate("11 Jan,2013");
// String event1 = event.getDate();
//
// textViewForDateHeader = (TextView)myView.findViewById(R.id.textViewHeadingDate);
// textViewForDateHeader.setText(event1);
DatabaseManager db = new DatabaseManager(mContext);
dateForEventList = db.getAllData1(CalendarAdapter.dateOfEventSingle);
for (Events l : dateForEventList) {
eventsRetrived = l.getEventData();
}
events = eventsRetrived.split(",");
// TextView tv = (TextView)myView.findViewById(R.id.grid_item_text);
// tv.setText(events[position]);
textViewTitle = (TextView) myView.findViewById(R.id.textViewTitle);
textViewTitle.setText(events[position]);
textViewDialogue = (TextView) myView.findViewById(R.id.textViewDialog);
textViewDialogue.setText(events[position]);
textViewDialogue.setVisibility(mExpanded[position] ? VISIBLE : GONE);
// textViewHeader = (TextView)myView.findViewById(R.id.textViewHeader);
// textViewHeader.setText(mHeader[position]);
// textViewHeader.setVisibility(mExpanded[position] ? VISIBLE : GONE);
buttonForCheckMark = (ImageButton) myView.findViewById(R.id.buttonForCheckMark);
buttonForCheckMark.setVisibility(mExpanded[position] ? VISIBLE : GONE);
buttonForDelete = (ImageButton) myView.findViewById(R.id.buttonForDelete);
buttonForDelete.setVisibility(mExpanded[position] ? VISIBLE : GONE);
buttonForRemainder = (ImageButton) myView.findViewById(R.id.buttonForRemainder);
buttonForRemainder.setVisibility(mExpanded[position] ? VISIBLE : GONE);
buttonForRemainder.setOnClickListener(new OnClickListener() {
#SuppressWarnings("static-access")
#SuppressLint("SimpleDateFormat")
public void onClick(View v) {
try {
Toast.makeText(mContext, "remainder saved..", Toast.LENGTH_SHORT).show();
} catch (Exception ex) {
Toast.makeText(mContext, "Exception in Remainder " + ex.toString(), Toast.LENGTH_SHORT).show();
}
//
}
});
buttonForCheckMark.setOnClickListener(new OnClickListener() {
public void onClick(View v){
Toast.makeText(mContext, "tapped on checkMark", Toast.LENGTH_SHORT).show();
Toast.makeText(mContext, " current Position tapped : " + position, Toast.LENGTH_SHORT).show();
if(position == 0) {
buttonForCheckMark.setBackgroundResource(R.drawable.ic_launcher);
buttonForDelete.setBackgroundResource(R.drawable.ic_navigation_cancel);
buttonForCheckMark.setClickable(false);
buttonForDelete.setClickable(true);
}
// change the status to 1 so the at the second clic , the else will be executed
// else {
// button.setBackgroundResource(R.drawable.ic_navigation_accept);
// status =0;//change the status to 0 so the at the second clic , the if will be executed
// }
// buttonForCheckMark.setBackgroundResource(R.drawable.ic_drawer);
}
});
buttonForDelete.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(mContext, "tapped on delete", Toast.LENGTH_SHORT).show();
if(position == 0) {
buttonForCheckMark.setBackgroundResource(R.drawable.ic_navigation_accept);
buttonForCheckMark.setClickable(true);
buttonForDelete.setBackgroundResource(R.drawable.ic_drawer);
buttonForDelete.setClickable(false);
// change the status to 1 so the at the second clic , the else will be executed
}
}
});
return myView;
}
public void toggle(int position) {
mExpanded[position] = !mExpanded[position];
notifyDataSetChanged();
}
/**
* Remember our context so we can use it when constructing views.
*/
private Context mContext;
/**
* Our data, part 1.
*/
private String[] mTitles =
{
"Event 1",
"Event 2",
"Event 3",
"Event 4",
"Event 5"
};
/**
* Our data, part 2.
*/
private String[] mDialogue =
{
"wuszuogwfuieffufuhuysugdueljwihadghgxdhgyhghsdgyigwuweyuqaGDHGYHGHGAdhgyhigxgxgeuyehu.",
"dgusduugyujguegytgujgdugwjhiuyg7wtqUYGYYgyijyiufufjguhgdugfhgfhgfgfhgfhghfghifgyi,dgwsdtgyfytfiuwt,",
"rtygygghtudggyjhgujtugdhhguyuaUUUUDJYUIDHUJHDIIDUJDHDUJHDIDIOUYhujtdugyhdgg",
"gjhuwjsgudggdudgjqhasdgdhgjdhushjaguhguwegagsdgygydgfgdcgycg",
"fhdgyhdfhfgdyhhwsddgyuduuufguugwugdfgugdgooduiuduiuduuduiuiuidudiiwdiou"
};
/**
* Our data, part 3.
*/
private boolean[] mExpanded =
{
false,
false,
false,
false,
false,
false,
false,
false
};
// private Integer[] mThumbIds = {
// R.drawable.remainder, R.drawable.remainder,
// R.drawable.remainder, R.drawable.remainder,
// R.drawable.remainder
//
// };
}
You cannot stop getView() method to be called automatically but you can solve your problem in alternative way.
You are inflating this layout to adapter
R.layout.activity_event_list
I am assuming your parent for this layout is Relative Layout with id as #+id/parent
Now in your getView method set the background color of row like this.
RelativeLayout parentLayout=(RelativeLayout)findViewById(R.id.parent);
parentLayout.setBackgroundColor(Color.WHITE);

When items are redrawn after invoking `invalidateViews()`

When are the items redrawn after invoking invalidateViews() ?
I ask because i try to refresh listItems after a bg-thread notify an image rsc was downloaded.
But nothing is updated. Only after exiting and re-entering the new icons are drawn.
I have an activity with adapter of type SettingValueAdapter extends BaseAdapter
it has a member:
private SettingsValue[] values;
it has two interesting methods:
#Override
public View getView(int position, View view, ViewGroup parent) {
AddressItem ai= (AddressItem)getItem(position);
DriveToNativeManager dnm = DriveToNativeManager.getInstance();
if (view == null) {
LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.address_item, null);
}
view.setTag(R.id.addressItem,ai);
view.setTag(position);
view.findViewById(R.id.fullAddressItemCol).setVisibility(View.VISIBLE);
view.findViewById(R.id.addressItemTouch).setVisibility(View.GONE);
view.findViewById(R.id.addressItemImage).setVisibility(View.GONE);
if (ai != null) {
...
}
view.findViewById(R.id.addressItemIconLayout).setVisibility(View.VISIBLE);
Drawable icon = ResManager.GetSkinDrawable(ai.getIcon() + ".bin");
((ImageView)view.findViewById(R.id.addressItemIcon)).setImageDrawable(icon);
..
}
}
public void refreshListIcons() {
// NativeManager nativeManager = AppService.getNativeManager();
// SettingsValue[] values = new SettingsValue[categories.length];
// for (int i = 0; i < categories.length; i++) {
// values[i] = new SettingsValue(categories[i].value, nativeManager.getLanguageString(categories[i].displayString), false);
// values[i].icon = ResManager.GetSkinDrawable(categories[i].iconName + ".bin");
// }
// adapter.setValues(values);
this.runOnUiThread(new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
}
});
}
I attach a callback to the bg-thread (c language) image downloading process.
The callback switches to the ui-thread and calls this refreshList:
public void refreshSearchIconsOnSearchActivity() {
Runnable refreshViewEvent = new Runnable() {
#Override
public void run() {
Activity currentActivity = AppService.getActiveActivity();
if (currentActivity instanceof SearchActivity) {
Log.d("w", "refreshSearchIconsOnSearchActivity callback running in thread "
+ Thread.currentThread().getId() );
//results list
((SearchActivity) currentActivity).refreshList();
}
}
};
AppService.Post(refreshViewEvent);
}
However, the images are done downloading and are not refreshed on the activity.
They are refreshed only when I leave an re-enter the activity.
What am I missing?
InvalidateViews just causes the listView to redraw itself. It will not call getView to do so, it just resets the current ones on screen- basically it just does
for(View child: getChildren()){
child.invalidate();
}
If you want to update the list, call notifyDataSetChanged on the adaptor.

Categories