Autore Topic: okHttp in asynctask?  (Letto 793 volte)

Offline Raffyna

  • Utente junior
  • **
  • Post: 104
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    htc wildfire
  • Sistema operativo:
    seven
okHttp in asynctask?
« il: 02 Settembre 2015, 10:04:37 CEST »
0
Salve,
 ho implementato le funzioni necessarie a fare richieste Http con ok http al fine di realizzare delle richieste bloccanti, ovvero far si che l'app resti in attesa fino a quando non riceve una risposta dal server.

La casse implementata è la seguente :

Codice (Java): [Seleziona]
public class okHttpRequest {

        //Creazione del client
        OkHttpClient client = new OkHttpClient();

        public String doGetRequest(String url) throws IOException {
            Request request = new Request.Builder()
                    .url(url)
                    .build();

            Response response = client.newCall(request).execute();
            return response.body().string();
        }



        public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

        // test data
        public String composizioneJson() {
                return "{\n" +
                        "\t\"tag\" : \"login\",\n" +
                        "\t\"user\" : {\n" +
                        "\t\t\"email\" : \"email@gmail.com\",\n" +
                        "\t\t\"pwd\" : \"abcdefgh\"\n" +
                        "\t}\n" +
                        "}";
        }

        public  String doPostRequest(String url, String json) throws IOException {
                RequestBody body = RequestBody.create(JSON, json);
                Request request = new Request.Builder()
                        .url(url)
                        .post(body)
                        .build();
                Response response = client.newCall(request).execute();
                return response.body().string();
        }
}


La chiamata dei metodi :

Codice (Java): [Seleziona]
 okHttpRequest example = new okHttpRequest();
            String getResponse = null;
            try {
                getResponse = example.doGetRequest(url);
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(getResponse);


            // issue the post request

            String json = example.composizioneJson();
            String postResponse = null;
            try {
                postResponse = example.doPostRequest(url, json);
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(postResponse);

durante la compilazione si presenta il seguente errore :
Codice (Java): [Seleziona]
09-02 09:54:13.967  32532-32532/it.reply.roma_managment E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: it.reply.roma_managment, PID: 32532
    android.os.NetworkOnMainThreadException
            at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147)
            at java.net.InetAddress.lookupHostByName(InetAddress.java:423)
            at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
            at java.net.InetAddress.getAllByName(InetAddress.java:215)
            at com.squareup.okhttp.internal.Network$1.resolveInetAddresses(Network.java:29)
            at com.squareup.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:187)
            at com.squareup.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:156)
            at com.squareup.okhttp.internal.http.RouteSelector.next(RouteSelector.java:98)
            at com.squareup.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:344)
            at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:327)
            at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:245)
            at com.squareup.okhttp.Call.getResponse(Call.java:267)
            at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:224)
            at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:195)
            at com.squareup.okhttp.Call.execute(Call.java:79)
            at it.reply.roma_management.library.okHttpRequest.doGetRequest(okHttpRequest.java:27)
            at it.reply.roma_managment.MainActivity$PlaceholderFragment.onCreateView(MainActivity.java:161)
            at android.support.v4.app.Fragment.performCreateView(Fragment.java:1789)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:955)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)
            at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:740)
            at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1501)
            at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:490)
            at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
            at android.support.v4.view.ViewPager.populate(ViewPager.java:1105)
            at android.support.v4.view.ViewPager.populate(ViewPager.java:951)
            at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1473)
            at android.view.View.measure(View.java:17473)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
            at android.support.v7.internal.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:124)
            at android.view.View.measure(View.java:17473)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
            at android.support.v7.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:444)
            at android.view.View.measure(View.java:17473)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
            at android.view.View.measure(View.java:17473)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1438)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:724)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:615)
            at android.view.View.measure(View.java:17473)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2622)
            at android.view.View.measure(View.java:17473)
            at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2030)
            at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1192)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1399)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1077)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5845)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
            at android.view.Choreographer.doCallbacks(Choreographer.

Cercando ho notato che tale errore si verifica quando si cerca di eseguire un'operazione nel thread principale e per risolverlo ci vorrebbe un asyncTask, ma in tal caso la chiamata non sarebbe più bloccante, come posso risolvere?

Grazie in anticipo per l'aiuto

Offline iClaude

  • Utente normale
  • ***
  • Post: 183
  • Respect: +13
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S5
  • Sistema operativo:
    Windows 10
Re:okHttp in asynctask?
« Risposta #1 il: 02 Settembre 2015, 10:46:50 CEST »
0
Avere connessioni internet bloccanti è una cattiva tecnica di programmazione, e difatti su Android sono impedite per default.
Piuttosto meglio impostare la tua UI in base ai dati che hai a disposizione.

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:okHttp in asynctask?
« Risposta #2 il: 02 Settembre 2015, 10:51:36 CEST »
0
Cercando ho notato che tale errore si verifica quando si cerca di eseguire un'operazione nel thread principale e per risolverlo ci vorrebbe un asyncTask, ma in tal caso la chiamata non sarebbe più bloccante, come posso risolvere?

Se usi okhttp in modo non bloccante, si preoccupa da solo di creare il thread secondario dove eseguire la richiesta di rete e notificarti la conclusione.

Viene messa a disposizione anche la versione "bloccante" se vuoi occuparti di persona di creare il thread secondario, per esempio per racchiudere in un unico asynctask più chiamate in sequenza ed eventuali elaborazioni pesanti alla fine.

Quindi:
- Se usi la versione bloccante, devi creare tu un asynctask o thread secondario dove eseguire la chiamata di rete
- Se ti serve una sorta di "blocco" delle operazioni o dell'app fintanto che non ritorna la risposta, devi crearlo artificialmente. Per esempio, poco prima di lanciare la richiesta di rete metti i button in stato "disable", lanci la richiesta di rete, quando ti ritorna a notifica di conclusione rimetti i button in stato "enable".
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Raffyna

  • Utente junior
  • **
  • Post: 104
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    htc wildfire
  • Sistema operativo:
    seven
Re:okHttp in asynctask?
« Risposta #3 il: 02 Settembre 2015, 11:16:17 CEST »
0
Ciao bradipo e grazie per la risposta.
Ho seguito i suggerimenti di questo link OkHttp ho quindi implementato la classe riportata nel post precedente, ma non capisco quale in quale modo effettuare la richiesta non bloccante. Potresti postarmi cortesemente un esempio ?

Grazie.

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:okHttp in asynctask?
« Risposta #4 il: 02 Settembre 2015, 11:47:11 CEST »
0
Guarda qua: https://github.com/square/okhttp/wiki/Recipes

La bloccante è la richiesta "sincrona".
La non bloccante è quella "asincrona", che infatti ha una callback per la notifica del termine.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Raffyna

  • Utente junior
  • **
  • Post: 104
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    htc wildfire
  • Sistema operativo:
    seven
Re:okHttp in asynctask?
« Risposta #5 il: 02 Settembre 2015, 15:43:36 CEST »
0
Ciao Bradipo,
grazie per il suggerimento come al solito riesci a risolvere i miei problemi :D
Ho solo un'ultima domanda. Ho implementato la richiesta dati con okhttp asincrona nel seguente modo :
Codice (Java): [Seleziona]
public class okHttpRequest {

    private final OkHttpClient client = new OkHttpClient();

    public void run() throws Exception {

        //Richiesta JSON
        /**
         * {
         *  "tag" : "vehicle",
         *  "type" : "list"
         *  }
         *  */

        RequestBody formBody = new FormEncodingBuilder()
                    .add("tag", "vehicle")
                    .add("type","list")
                    .build();

        Request request = new Request.Builder()
                .url("url")
                .post(formBody)
                .build();


        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                    Log.e("okHttp", "Fallimento");
            }

            @Override
            public void onResponse(Response response) throws IOException {

                if (!response.isSuccessful())
                    throw new IOException("Unexpected code " + response);


                Headers responseHeaders = response.headers();
                for (int i = 0; i < responseHeaders.size(); i++) {
                    System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
                }

                System.out.println("Body ==> " + response.body().string());

            }
        });
    }

Il problema che mi si presenta è che il body della riposta è sempre "Query Empty", hai qualche suggerimento a riguardo ?

In pratica invio una richiesta JSON ad un serve Apache e mi aspetto che tale server risponda ancora con un formato Json.
Grazie in anticipo.
« Ultima modifica: 02 Settembre 2015, 15:47:27 CEST da Raffyna »

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:okHttp in asynctask?
« Risposta #6 il: 02 Settembre 2015, 19:04:57 CEST »
0
Come prima cosa, se possibile, sarebbe meglio verificare cosa risponde il server apache. Perchè, molto sinceramente, sarebbe meglio se il problema fosse nel server apache o comunque nel modo di comporre la richiesta okhttp.

Dipende da quanto testato è il server e se è la prima volta che ti interfacci con esso.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Raffyna

  • Utente junior
  • **
  • Post: 104
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    htc wildfire
  • Sistema operativo:
    seven
Re:okHttp in asynctask?
« Risposta #7 il: 08 Settembre 2015, 10:21:30 CEST »
0
Ciao Bradipo,
ho controllato un pò ed il problema era del server meno male:D.
Avrei una domanda:
il metodo di richiesta al server è il seguente:
Codice (Java): [Seleziona]
        client.newCall(request).enqueue(new Callback() {

            @Override
            public void onFailure(Request request, IOException e) {
                    Log.e("okHttp", "Fallimento");
            }

            @Override
            public void onResponse(Response response) throws IOException
            {

                if (!response.isSuccessful())
                    throw new IOException("Unexpected code " + response);


                Headers responseHeaders = response.headers();
                for (int i = 0; i < responseHeaders.size(); i++) {
                    System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
                }
                Log.e("okHttp","okHttp Body ==> "+response.body().string());


            }
        });

Il problema è che
Codice: [Seleziona]
response.body().string() mi servirebbe all'esterno del metodo di callback(). Ho provato ad implementare i metodi all'interno di un singleton e con il set e get a leggere il dato in una classe diversa da quella di implementazione ma il programma crasha. Avresti qualche suggerimento su come leggere il dato all'esterno del metodo?

Grazie in anticipo.

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:okHttp in asynctask?
« Risposta #8 il: 08 Settembre 2015, 10:24:06 CEST »
0
Se la stringa è relativamente corta, io la passerei all'activity con un "message" che viene ricevuto da un handler. E' una soluzione con un po' di overhead, però è stabilissima e riutilizzabile in ogni possibile scenario.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Raffyna

  • Utente junior
  • **
  • Post: 104
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    htc wildfire
  • Sistema operativo:
    seven
Re:okHttp in asynctask?
« Risposta #9 il: 08 Settembre 2015, 10:28:09 CEST »
0
Grazie mille provo subito :-P