I am trying to display images in a gridView. The images come from an research on an ElasticSearch server. The user give a keyword in a textfield, the result of the query on ElasticSearch is list of string (urls of images) and the images are displayed in the gridView.
The action when I press a button in order to make the research :
public void sendMessage(View view){
imgAdapter.clearmThumbIds(); //mThumbs is a list of string (urls image)
gridView = (GridView) findViewById(R.id.grid_view);
EditText editText = (EditText) findViewById(R.id.searchBar);
String message = editText.getText().toString();
try {
eSearchElastic.ESE(imgAdapter,message);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Etape 2");
gridView.setAdapter(imgAdapter);
}
eSearchElastic.java
public static void ESE (final ImageAdapter imgAdapter,final String keyword)throws ClientProtocolException, IOException {
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>(){
#Override
protected Void doInBackground(Void... params) {
//Build the query, connect to ElasticServer and receive a list or urls of image as answer
System.out.println("Etape 1");
return null;
}
};
task.execute();}
And the result of this print Etape2 before Etape1 and I would like this line "gridView.setAdapter(imgAdapter)" is executed only after the background process/thread of eSearchElastic is finished.
How can I do that?
Just call gridView.setAdapter(imgAdapter); in the onPostExecute() method inside your AsyncTask instead of calling it from sendMessage(). That is guaranteed to be called only after the doInBackground() method finishes, and will be called on the main thread, so it's safe to touch the UI.
eg:
public static void ESE (final GridView gridView, final ImageAdapter imgAdapter, final String keyword) throws ClientProtocolException, IOException {
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>(){
#Override
protected Void doInBackground(Void... params) {
// Build the query, connect to ElasticServer and receive a list or urls of image as answer
System.out.println("Etape 1");
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
gridView.setAdapter(imgAdapter);
}
};
task.execute();
}
Related
I'm trying to learn how to work with AsyncTask. I have code in the doInBackground that returns a String array, and a callback that invokes an interface to return it to the MainActivity. I am successfully executing the AsyncTask.
The problem is: trying to return the array via onPostExecute I'm getting an arguments error; it won't accept the array. How do I use the onPostExecute method to return the value feeds? I have tried to change the result of doInBackground but that wouldn't accept an array either.
Here is the interface called in MainActivity:
interface DownloadFinishedListener {
void notifyDataRefreshed(String[] feeds);}
Here is the callback:
try {
mCallback = (DownloadFinishedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement DownloadFinishedListener");
}
and here is the AsyncTask:
public class DownloaderTask extends AsyncTask<Integer, Void, String> {
#Override
protected String doInBackground(Integer... params) {
downloadTweets(params);
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
mCallback.notifyDataRefreshed(s); //trying to send back feeds
}
// Simulates downloading Twitter data from the network
private String[] downloadTweets(Integer resourceIDS[]) {
final int simulatedDelay = 2000;
String[] feeds = new String[resourceIDS.length];
try {
for (int idx = 0; idx < resourceIDS.length; idx++) {
InputStream inputStream;
BufferedReader in;
try {
// Pretend downloading takes a long time
Thread.sleep(simulatedDelay);
} catch (InterruptedException e) {
e.printStackTrace();
}
inputStream = mContext.getResources().openRawResource(
resourceIDS[idx]);
in = new BufferedReader(new InputStreamReader(inputStream));
String readLine;
StringBuffer buf = new StringBuffer();
while ((readLine = in.readLine()) != null) {
buf.append(readLine);
}
feeds[idx] = buf.toString();
if (null != in) {
in.close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return feeds;
}
}
The problem is: trying to return the array via onPostExecute I'm
getting an arguments error; it won't accept the array
You need to pass String Array as last generic argument to AsyncTask which is return type of doInBackground and argument type of onPostExecute.
Do following changes :
1. extend AsyncTask as:
public class DownloaderTask extends AsyncTask<Integer, Void, String[]>
2. Change doInBackground method return type from String to String[] :
#Override
protected String[] doInBackground(Integer... params) {
downloadTweets(params);
return downloadTweets(params);
}
3. Change onPostExecute paramter type from String to String[] :
protected void onPostExecute(String[] s) {
super.onPostExecute(s);
mCallback.notifyDataRefreshed(s); //trying to send back feeds
}
You should pass String[] as last argument in your AsyncTask not just String as you are doing and your AsyncTask should look like similar to this:
public class DownloaderTask extends AsyncTask<Integer, Void, String[]> {
#Override
protected String[] doInBackground(Integer... params) {
return downloadTweets(params);;
}
#Override
protected void onPostExecute(String[] s) {
super.onPostExecute(s);
mCallback.notifyDataRefreshed(s); //trying to send back feeds
}
}
Hello so I have already an expirience with AsyncTask so I can manage to get some data with PHP scripts from an SQL Server and parsed them with JSON. Now what I would want is to know how can I use the AsyncTask in order to load images to some activities. Also is there anyway that I can call the AsyncTask before the app starts? because that would be really helpful too.
I don't have any adapters I am just using this for the AsyncTask:
// The definition of our task class
private class PostTask extends AsyncTask<String, Integer, String> {
private String postName;
private JSONObject jsonvar = new JSONObject();
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
this.postName = params[0];
String status = "";
List<NameValuePair> values = new ArrayList<NameValuePair>();
values.add( new BasicNameValuePair( "username", this.postName ) );
final AndroidHttpClient client = AndroidHttpClient.newInstance( "" );
HttpResponse response = HttpHelper.postResponse( client, Register.phpUrl, values );
String data = HttpHelper.getData( response );
try {
jsonvar = new JSONObject(data);
status=jsonvar.getString("status");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
client.close();
return status;
}
// #Override
// protected void onProgressUpdate(Integer... values) {
// super.onProgressUpdate(values);
// }
#Override
protected void onPostExecute(String status) {
String session = "", status_message = " ";
try {
status_message = jsonvar.getString("status_message");
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
super.onPostExecute(status);
}
}
}
As i can tell with information provided, supposing that what you read from your server is the image URL and obtain it in JSON format, what i would do is writing a listener to your AsyncTask, calling it in onPostExecute method, and loading it in your Activity using PicassoImagesLoader
Something like:
private class PostTask extends AsyncTask<String, Integer, String> {
public interface onLoadFinishedListener {
public void onLoadFinished(JSONObject response)
}
protected JSONObject onPostExecute(JSONObject response){
onLoadFinished(response);
}
}
And in your Activity:
public myActivity extends Activity implements PostTask.onLoadFinishedListener {
#Override
onLoadFinished(JSONObject response){
Picasso.with(this).load(response.getString("url")).into(imageView);
}
}
Something like this would help :)
I want to parse JSON every few seconds. My idea is by constantly parsing it to see if there are some changes in it and if there are to get them and update my views (mostly TextViews). I have a Fragment, called MyFragment. In its onCreateView I am executing the following: new MyTask().execute(myJSONUrl);. Some code:
class MyTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
//getJSONString(String url) - my method for getting the JSON from URL
return getJSONString(params[0]);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (result == null || result.length() == 0) {
Log.w(TAG," JSON IS **null** ");
Toast.makeText(getActivity().getApplicationContext(), "JSON IS NULL", Toast.LENGTH_SHORT).show();
} else {
try{
JSONObject root = new JSONObject(result);
// Here i get what i need from the JSONObject and everything works fine.
} catch (Exception e) {
e.printStackTrace();
}
}
Now how to parse the JSON from URL every n seconds? I have tried using ScheduledExecutorService, Timer and Thread but nothing seems to work. Thanks in advance :-)
When you really throw the battery concerns out of the window:
Change class MyTask extends AsyncTask<String, Void, String> to class MyTask extends AsyncTask<String, String, Void>
Do the following:
protected String doInBackground(String... params) {
//getJSONString(String url) - my method for getting the JSON from URL
while(isCancelled() == false) {
try {
Thread.sleep(1000* 5); // only do this every 5 seconds.
} catch (InterruptException ex) {}
publishResult(getJSONString(params[0]));
}
}
public void onResultPublished(String result) {
// stuff that happened in onResult before...
}
You emit strings as a result and handle it in onResultPublished (this method is executed on the UI thread so it's safe to modify ui here).
Don't forget to cancel the asynctask.
I want to start an AsyncTask inside another AsyncTask.
I'm trying to do this by starting the second AsyncTask in 'onPostExecute' of the first AsyncTask. The result is that the second AsyncTask starts after the first has finished.
How can I solve this?
Thank you
here's the code
private class Parse extends AsyncTask<Void, Void, Void>{
Document doc = null;
Element son = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
try {
doc = Jsoup.connect("MY_URL").get();
son= doc.body();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
for(CONDITION){
//MY_CODE
new DownloadImageTask().execute();
}
}
}
This is the second AsyncTask
private class DownloadImageTask extends AsyncTask<String, Void, String> {
Bitmap bitmap;
ImageView image = new ImageView(Events.this);
#Override
protected void onPreExecute() {
};
protected String doInBackground(String... urls) {
try {
URL url = new URL("MY_URL");
bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
First, please refer to the oficial documentation to have a best understanding about AsyncTask: http://developer.android.com/reference/android/os/AsyncTask.html
The onPostExecute runs in the main thread, after the background task finishes. This method is designed this way to be used to comunicate with the UI thread to handle the execution.
If you want to run the second AsyncTask with your background code, or just after it started, you have to do this on the doInBackground method.
This class causing me android.os.NetworkOnMainThreadException,i know that i have to use asyncTask to make it but i can't figure out how because i am using 1 fragments and this make my application very slow especially when i laod bitmaps, can any one help me please.
public class ContainerData {
static public Context context;
public ContainerData() {
}
public static ArrayList<Feed> getFeeds(String feedurl){
SAXParserFactory fabrique = SAXParserFactory.newInstance();
SAXParser parseur = null;
ArrayList<Feed> feeds = null;
try {
parseur = fabrique.newSAXParser();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
URL url = null;
try {
url = new URL(feedurl);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
DefaultHandler handler = new ParserXMLHandler();
try {
parseur.parse(url.openConnection().getInputStream(), handler);
feeds = ((ParserXMLHandler) handler).getData();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return feeds;
}
}
If you use AsyncTask make sure getFeeds is called inside the doInBackground(...) callback
Regardless of whether you use a fragment or not, you're still trying to perform Network activity on the main thread.
Create a generic class that extends AsyncTask which can perform all your parsing.
public class MyTaskHandler extends AsyncTask<String, Integer, Boolean>
{
#Override
protected void onPreExecute()
{
//Could display progress dialog here
}
#Override
protected Boolean doInBackground(String... params)
{
//Implement your parser here
}
#Override
protected void onPostExecute(Boolean result)
{
//Check result, dismiss dialog etc
}
}
Then create a new instance of MyTaskHandler and run it...
MyTaskHandler myTask = new MyTaskHandler();
myTask.execute("http://www.myxmlsite.com/lists.xml");
The execute method can take (String... params) so you can pass for example a URL,and retrieve it in doInBackground(String... params)
#Override
protected Boolean doInBackground(String... params)
{
//Implement your parser here
String urlToParse = params[0];
}
Best of luck.