2017-08-03 6 views
0

Je travaille sur du code qui va extraire des informations JSON de Facebook et les placer dans une vue EditText. Le problème que je rencontre est que puisque la fonction que j'appelle pour récupérer les données est une fonction Async, les données sont récupérées APRÈS que ma fonction onCreate se termine pour mon activité, donc le texte ne peut pas être mis à jour car il est nul . Comment puis-je m'assurer que ma méthode OnCreate ne se termine pas tant que les données ne sont pas récupérées?OnCreate se termine avant que les données puissent être récupérées de manière asynchrone

Voici ma classe d'activité:

public class PersonalInfoMain extends AppCompatActivity implements GraphService.OnDownloadComplete { 

    public EditText mName; 
    public String name; 

    String mValue, mField; 

    private static final String TAG = "PersonalInfoMain"; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     Log.d(TAG, "onCreate: starts"); 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_personal_info_main); 

     mName = (EditText) findViewById(R.id.editText_name); 

     //Calling GraphService class 
     GraphService mGraphService = new GraphService(this); 
     mField = "name"; 
     mGraphService.execute(mField); 
     mName.setText(name); 
    } 
} 

    //My Callback function located in the same activity: 
    @Override 
    public void onDownloadComplete(String s) { 
      name = s; 
    } 

Voici ma classe j'étiquetée GraphService pour tirer des informations de Facebook:

public class GraphService extends AsyncTask<String, Void, String>{ 

private static final String TAG = "GraphService"; 

private String mField; 
private String mValue; 

private final OnDownloadComplete mCallback; 

public interface OnDownloadComplete{ 
    void onDownloadComplete(String data); 
} 

public GraphService(OnDownloadComplete callback){ 
    mCallback = callback; 
} 

@Override 
public String doInBackground(final String... params) { 
    Log.d(TAG, "doInBackground: starts"); 

    mField = params[0]; 

    //Beginning of Facebook implementation 
    GraphRequest request = GraphRequest.newMeRequest(
     AccessToken.getCurrentAccessToken(), 
     new GraphRequest.GraphJSONObjectCallback() { 

      @Override 
      public void onCompleted(JSONObject object, GraphResponse response) { 
       try { 
         mValue = object.getString(mField); 

       } catch (JSONException e) { 
        e.printStackTrace(); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    ); 

    Bundle parameters = new Bundle(); 
    parameters.putString("fields", mField); 
    request.setParameters(parameters); 
    request.executeAsync(); 
    return mValue; 

} 

@Override 
protected void onPostExecute(String s) { 
    if(mCallback != null){ 
     mCallback.onDownloadComplete(s); 
    } 
} 

My Android Monitor affiche ce flux de travail:

D/MainActivity: onCreate: starts 
D/MainActivity: isLoggedIn: starts 
D/MainActivity: isLoggedIn: ends 
D/MainActivity: onCreate: ends 
D/PersonalInfoMain: onCreate: starts 
D/PersonalInfoMain: onCreate: name = null 
D/GraphService: doInBackground: starts 
D/PersonalInfoMain: onCreate: ends 
D/PersonalInfoMain: onResume: starts 
D/PersonalInfoMain: onResume: name = null 
D/GraphService: doInBackground: ends 
D/PersonalInfoMain: onResume: ends 
D/GraphService: onPostExecute: starts 
D/PersonalInfoMain: onDownloadComplete: starts 
D/PersonalInfoMain: onDownloadComplete: ends 
D/GraphService: onPostExecute: ends 
D/GraphService: onCompleted: starts, JSON object = {"name":"Tom"}, response = {"name":"Tom"} 
D/GraphService: onCompleted: json object:{"name":"Tom"} 
D/GraphService: onCompleted: ends 

Comme vous pouvez le voir, ma méthode .setText() dans mon activité la définit sur une valeur null car la tâche asynchrone (méthode onCompleted()) n'a pas encore retourné les données. Comment puis-je m'assurer que ma méthode OnCreate ne se termine pas tant que les données ne sont pas récupérées?

J'apprécierais n'importe quel conseil.

Merci.

Répondre

0

Vous ne pouvez pas et vous ne devriez pas comme vous faites une requête réseau asynchrone. Il vaut mieux appeler simplement la méthode setText une fois que vous avez besoin des données de l'appel réseau.

// Ma fonction de rappel situé dans la même activité:

@Override 
public void onDownloadComplete(String s) { 
     mName.setText(s); 
} 
+0

Salut Sunil, J'ai toujours entendu dire que les actions courtes comme une requête réseau doivent être appelées de manière asynchrone. Pouvez-vous expliquer pourquoi je ne devrais pas faire ça? J'ai essayé votre code et il ne met toujours pas à jour mName car le code de récupération JSON est appelé après la fin de la fonction onDownloadComplete (comme vous pouvez le voir dans le Logcat) – Ozzy

+0

Oui je viens de découvrir que vous faites de nouveau GraphRequest asynchrone à l'intérieur de doInBackground, dans ce cas, vous appelez return avant même que vous obteniez le résultat de la requête. Ici, vous n'avez pas besoin d'AsyncTask car vous pouvez appeler directement GraphRequest. –

0

Peut-être que vous pouvez essayer de déplacer le code de votre onDownloadComplete() à onPostExecute(). Personnellement, je ne pense pas qu'il soit nécessaire d'utiliser le

interface publique OnDownloadComplete {

void onDownloadComplete(String data); 

}

ici. Après l'exécution de la méthode doInBackground(), le résultat (mValue) sera passé à onPostExecute (String s) en tant que s.

Dans onPostExecute(), vous pouvez mettre à jour votre interface utilisateur.

Ceci est ma première réponse ici. Si quelque chose ne va pas, dites-moi s'il vous plaît.