3

I'm trying to parse data from my server in Java with jsoup. I wrote a new function and it should return data in string format, but it returns blank string. Here is my code:

public String doc;

public String pare(final String url){
        Thread downloadThread = new Thread() {
            public void run() {
                try {
                    doc = Jsoup.connect(url).get().toString();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };
        downloadThread.start();
        return  doc;
}
user47823
  • 49
  • 1
  • 6

4 Answers4

2

You're returning the doc object immediately, before the thread has had a chance to add any data to it, so it should be no surprise that this returns empty. You can't return threaded information in this way, and instead will need to use some type of call-back mechanism, one that notifies you when the thread is done and when data is ready to be consumed.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • When I put Log.i("info",doc); after Jsoup.connect(url).get().toString() it returns my data. What call-back mechanism should I use? – user47823 Mar 12 '16 at 18:21
  • 1
    THat's because you're doing it on the same thread as the download. You need to research what a thread is and how it works. – Gabe Sechan Mar 12 '16 at 18:21
  • 1
    @user47823: exactly as Gabe states. As for callback mechanism, I don't do Android, so I don't know what is standard for that environment. If this were my non-android code, I could do this with any observer type design pattern such as with a PropertyChangeListenerSupport object added to the threaded class as well as add and remove PropertyChangeListener methods for the same class, and then call a propertyChange method on the support object when the method has completed itself. – Hovercraft Full Of Eels Mar 12 '16 at 18:26
1

On android platform, you shouldn't ask Jsoup to download anything for you. Under the hood, Jsoup make use of HttpUrlConnection. This class is notoriously slow and has some known issues.

Use a faster alternative instead: Volley.

Here is the function in your post taking advantage of Volley. In the following sample code, I'm using a CountDownLatch to wait for the data.

private static RequestQueue myRequestQueue = null;

public String pare(final String url) throws Exception {   
   final String[] doc = new String[1];
   final CountDownLatch cdl = new CountDownLatch(1);

   StringRequest documentRequest = new StringRequest( //
        Request.Method.GET, //
        url, //
        new Response.Listener<String>() {
           @Override
           public void onResponse(String response) {
               doc[0] = Jsoup.parse(response).html();
               cdl.coutDown();
           }
        }, //
        new Response.ErrorListener() {
           @Override
           public void onErrorResponse(VolleyError error) {
               Log.e("MyActivity", "Error while fetching " + url, error);
           }
        } //
   );

   if (myRequestQueue == null) {
       myRequestQueue = Volley.newRequestQueue(this);
   }

   // Add the request to the queue...
   myRequestQueue.add(documentRequest);

   // ... and wait for the document.
   // NOTA: User experience can be a concern here. We shouldn't freeze the app...
   cdl.await();

   return doc[0];
} 
Stephan
  • 41,764
  • 65
  • 238
  • 329
  • If I run this code it creates a blanl screen, and app stops responding, what am I doing wrong? – user47823 Mar 13 '16 at 20:44
  • @user47823 the thread you are using is blocked by `cdl.await()` that s why the app stops responding. Call `pare` in another thread. – Stephan Mar 13 '16 at 20:54
0

I totally agree with the above answer. You can follow any of the below tutorials for fetching data from server

http://www.androidhive.info/2014/05/android-working-with-volley-library-1/

http://www.vogella.com/tutorials/Retrofit/article.html

These two are the best libraries for Network calls in android

Arshad
  • 1,262
  • 16
  • 25
0

Before the return statement add a downloadThread.join(). This will wait until the thread has finished and put the response into doc. But: Doing so you will loose all benefit from the asynchronous execution, it's behaving the same as you just would code:

public String pare(final String url){
    return Jsoup.connect(url).get().toString();
}
Heri
  • 4,368
  • 1
  • 31
  • 51