2017-08-14 3 views
3

J'ai créé un RetroFitService pour renvoyer certains objets. Dans MainActivity, j'appelle le service avec un simple clic. Il semble que j'obtienne une sorte d'objet, mais je ne pense pas qu'il soit réellement renvoyé par l'API REST que j'ai spécifiée. Il apparaît dans le débogueur, mais ses attributs sont nuls:Objet Retrofit retourné comme nul

bFetch.setOnClickListener(v -> { 
v.startAnimation(AnimationUtils.loadAnimation(this, R.anim.image_click)); 
RetrofitService service = ServiceFactory.createRetrofitService(RetrofitService.class, RetrofitService.SERVICE_ENDPOINT); 
service.getPosts() 
.subscribeOn(Schedulers.newThread()) 
.observeOn(AndroidSchedulers.mainThread()) 
.subscribe(new Subscriber <Post>() { 
    @Override 
    public final void onCompleted() { 
    Log.e("RetrofitService", "Retrofit Request Completed!"); 
    } 

    @Override 
    public final void onError(Throwable e) { 
    Log.e("RetrofitService", e.getMessage()); 
    } 

    @Override 
    public final void onNext(Post post) { 
    if (post != null) { 
    // TODO: Some object is returned but its properties are null 
    Log.e("RetrofitService", "Returned objects: " + post); 
    Log.e("RetrofitService", "Object Id: " + post.getObjectId()); 
    mCardAdapter.addData(post); 
    } else { 
    Log.e("RetrofitService", "Object returned is null."); 
    } 

    } 

}); 

}); 

} 

enter image description here

Service:

public interface RetrofitService { 

String SERVICE_ENDPOINT = "https://parseapi.back4app.com/"; 

@Headers({ 
    "X-Parse-Application-Id: asdf", 
    "X-Parse-REST-API-Key: asdf" 
}) 
@GET("/classes/Post") 
Observable <Post> getPosts(); 

/*curl -X GET \ 
     -H "X-Parse-Application-Id: asdf" \ 
     -H "X-Parse-REST-API-Key: asdf" \ 
https://parseapi.back4app.com/classes/Post*/ 

} 

La boucle fonctionne très bien. Je ne reçois aucune erreur. Qu'est-ce qui pourrait mal tourner? ? Est ma méthode @GET incorrect d'une certaine manière `

Pour la fin, voici le ServiceFactory classe:

public class ServiceFactory { 

    /** 
    * Creates a retrofit service from an arbitrary class (clazz) 
    * @param clazz Java interface of the retrofit service 
    * @param endPoint REST endpoint url 
    * @return retrofit service with defined endpoint 
    */ 
    public static <T> T createRetrofitService(final Class<T> clazz, final String endPoint) { 
     final RestAdapter restAdapter = new RestAdapter.Builder() 
       .setEndpoint(endPoint) 
       .build(); 
     T service = restAdapter.create(clazz); 

     return service; 
    } 
} 

Et mon build.gradle parce que je suis conscient qu'il ya des incohérences entre toutes les différentes versions: Rénovation

dependencies { 

    compile fileTree(dir: 'libs', include: ['*.jar']) 
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 
     exclude group: 'com.android.support', module: 'support-annotations' 
    }) 
    compile 'com.android.support:appcompat-v7:25.3.1' 
    compile 'com.android.support.constraint:constraint-layout:1.0.2' 
    testCompile 'junit:junit:4.12' 

    /* ReactiveX */ 
    compile 'io.reactivex:rxjava:1.0.17' 
    compile 'io.reactivex:rxandroid:0.23.0' 

    /* Retrofit */ 
    compile 'com.squareup.retrofit:retrofit:1.9.0' 

    /* OkHttp3 */ 
    compile 'com.squareup.okhttp3:okhttp:3.8.1' 

    /* RecylerView */ 
    compile 'com.android.support:recyclerview-v7:25.3.1' 

    /* CardView */ 
    compile 'com.android.support:cardview-v7:25.3.1' 

    /* Parse */ 
    compile 'com.parse:parse-android:1.13.0' 

} 

Poste classe:

public class Post implements Serializable { 

    private static final String CLASS_NAME = "Post"; 

    private String objectId; 
    private String text; 

    public Post(String objectId) { 
     this.setObjectId(objectId); 
    } 

    public static String getClassName() { 
     return CLASS_NAME; 
    } 

    public String getObjectId() { 
     return objectId; 
    } 

    private void setObjectId(String objectId) { 
     this.objectId = objectId; 
    } 

    public String getText() { 
     return text; 
    } 

    public void setText(String text) { 
     this.text = text; 
    } 

Curl Réponse:

>  https://parseapi.back4app.com/classes/Post/ 
    % Total % Received % Xferd Average Speed Time Time  Time Current 
           Dload Upload Total Spent Left Speed 
100 259 100 259 0  0 360  0 --:--:-- --:--:-- --:--:-- 395{"results":[{"objectId":"ktEfgr1pFt","text":"Hello World.","createdAt":"2017-08-14T14:07:52.826Z","updatedAt":"2017-08-14T14:07:52.826Z"},{"objectId":"Mmh8l9gjCk","text":"Hello?","createdAt":"2017-08-14T15:19:01.515Z","updatedAt":"2017-08-14T15:19:03.743Z"}]} 

FINAL MISE A JOUR: j'ai changé la méthode onNext() du RetrofitService de passer dans le CardAdapter, bien que non représentée ici et dépasse le cadre de la question.

@Override 
public final void onNext(PostResponse postResponse) { 
if (postResponse != null) { 
    // TODO: Some object is returned but its properties are null 
    Log.e("RetrofitService", "Objects successfully added to RecyclerView Adapter."); 
    Log.e("RetrofitService", "Returned objects: " + postResponse.getResults()); 
    Log.e("RetrofitService", "Text " + postResponse.getResults().get(0).getText()); 

    mCardAdapter.addData(postResponse); 
    // 
} else { 
    Log.e("RetrofitService", "Object returned is null."); 
} 

} 
+0

1.0.0 On dirait que vous essayez d'aller chercher des objets qui sont créés par Parse sdk. Assurez-vous que votre structure de données de classe Post correspond à ce que le point de terminaison renvoie (utilisez String par exemple). Et btw je masque l'URL et les informations d'identification de la question. –

+1

J'ai mis à jour ma question avec l'objet Post. Je ne vois pas vraiment de problème avec ça ... – santafebound

+0

Pourriez-vous également fournir la réponse json de curl -X GET -H "X-Parse-Application-Id: asdf" -H "X-Parse-REST-API -Key: asdf "https://parseapi.back4app.com/classes/Post –

Répondre

2

Essayez d'utiliser la classe suivante dans RetrofitService

@GET("/classes/Post") 
Observable <PostResponse> getPosts(); 

wrapper PostResponse classe

public class PostResponse { 
    private List<Post> results; 

    public List<Post> getResults() { 
     return results; 
    } 

    public void setResults(List<Post> results) { 
     this.results = results; 
    } 
} 
+0

Vous les gars, il est difficile pour moi de récompenser la question. Les deux réponses ont certainement aidé. Et oui, j'ai dû emballer la liste que je retournais dans la classe que vous avez fournie ici. – santafebound

+0

Je pense que Torsten mérite une récompense plus que moi. Il a répondu en premier :) –

+1

Cool, mais je pense que la réponse devrait également inclure la partie sur la barre oblique afin que les autres personnes obtiennent ce bit. Acclamations gars. – santafebound

1

Selon la mise à jour de votre question, vous recevez pas un seul objet, mais un objet avec une collection de Post objets.

Vous devez donc ajouter une classe:

public class Results { 
    List<Post> results = ArrayList<>() 
} 

Ensuite, mettre à jour votre méthode d'interface API pour revenir Observable<Results>:

Observable <Results> getPosts(); 

Et dans l'abonnement, vous pouvez enfin accéder à l'objet Result avec le Champ results contenant la collection d'objets Post.


Une erreur mineure est que votre URL de base point final a slash:

String SERVICE_ENDPOINT = "https://parseapi.back4app.com/"; 

En même temps, votre méthode API a slash au début du chemin:

@GET("/classes/Post") 
Observable <Post> getPosts(); 

Autant que je me souvienne avec retrofit, vous devriez avoir slash à la fin de l'adresse de point de terminaison ou slash début dans les méthodes de l'API, sinon cela ne peut pas w ork correctement.

Celui-ci devrait être correct:

String SERVICE_ENDPOINT = "https://parseapi.back4app.com"; // No slash here 
@GET("/classes/Post") // Keep slash here, or vice verse 
Observable<Results> getPosts(); 

Juste quelques commentaires sur votre section dépendances:

Y at-il une raison particulière que vous utilisez io.reactivex:rxandroid la version 0.23.0 alors que la dernière écurie est 1.2.1?

Vous n'avez pas besoin io.reactivex:rxjava:1.0.17 dépendance, comme la modernisation 1.9.0 dépend déjà rxjava

+0

Merci. Vous avez raison sur la barre oblique. J'ai nettoyé mes dépendances. J'utilise seulement 0.23.0 parce que c'est là que j'ai travaillé (dans une implémentation légèrement différente) dans un projet précédent. On dirait que Retrofit a traversé une tonne de changements récemment. Malheureusement, je reçois toujours des attributs d'objet null. Peut-être que c'est parce que je retourne une liste et que je ne la traite pas comme telle, comme l'a indiqué Torsten. – santafebound

+0

Juste une note, il semble que '' RetrofitService.getPosts: URL chemin "classes/Post" doit commencer par '/'. '', Selon mon moniteur. – santafebound

+0

@santafebound Vous avez publié le corps de réponse json et j'ai mis à jour ma réponse. Vous désérialisez une collection d'objets Post enveloppés dans un autre objet dans le champ de résultat en un seul objet Post. C'est la vraie erreur. Pas une barre oblique –