Je sais qu'il y a déjà beaucoup de questions avec ce titre mais je n'ai toujours pas trouvé de solution pour mon cas.
J'ai le code suivant qui obtient les données des utilisateurs d'une base de données en ligne. Le problème est, comme indiqué dans le titre, que le AsyncTask
ne démarre pas.
Voici mon code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getData(); // retrieves "friends" data from database
FloatingActionButton btn3 = (FloatingActionButton) findViewById(R.id.button_add_new_friend);
btn3.setBackgroundTintList(getResources().getColorStateList(R.color.Blonde));
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LayoutInflater layoutInflater = LayoutInflater.from(profile.this);
View promptView = layoutInflater.inflate(R.layout.input_new_friend, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(profile.this);
alertDialogBuilder.setView(promptView);
final EditText editText1 = (EditText) promptView.findViewById(R.id.edittext_addnewfriend);
// setup a dialog window
alertDialogBuilder.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
InputStream is = null;
// add values to the database
String friend = "" + editText1.getText();
// Verify the user in the USERS database - get users data from the dabase
GetDataJSON g = new GetDataJSON();
g.execute();
if (friends.contains(friend)) // if you are already friends with that user
Toast.makeText(getApplicationContext(), "You are already friends with that user!",
Toast.LENGTH_LONG).show();
else {
if (!users.contains(friend)) // the user doesn't exist in our database
Toast.makeText(getApplicationContext(), "That user doesn't exist! You either haven't introduced the right email or he's not a registered user within Poinder.",
Toast.LENGTH_LONG).show();
else // the user exists so we add him to the friends list
{
//do something
}
}
// Getting the users
protected void showList2(){
try {
JSONObject jsonObj = new JSONObject(myJSON);
people = jsonObj.getJSONArray(TAG_RESULTS);
for(int i=0;i<people.length();i++){
JSONObject c = people.getJSONObject(i);
String user = c.getString(TAG_USER);
String email = c.getString(TAG_EMAIL);
Double location_latitude = c.getDouble(TAG_LATITUDE);
Double location_longitude = c.getDouble(TAG_LONGITUDE);
users.add(email);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
// Getting the users
private class GetDataJSON extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
DefaultHttpClient httpclient = new DefaultHttpClient(new BasicHttpParams());
HttpPost httppost = new HttpPost("http://xxxxxxx/friends_out.php");
// Depends on your web service
httppost.setHeader("Content-type", "application/json");
InputStream inputStream = null;
String result = null;
try {
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
inputStream = entity.getContent();
// json is UTF-8 by default
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
result = sb.toString();
} catch (Exception e) {
// Oops
}
finally {
try{if(inputStream != null)inputStream.close();}catch(Exception squish){}
}
return result;
}
@Override
protected void onPostExecute(String result){
myJSON=result;
showList2();
}
}
Une idée de quelle autre méthode devrais-je utiliser à la place? Ou de préférence comment je devrais modifier celui-ci pour travailler et des idées pourquoi mon AsyncTask
ne démarre jamais?
EDIT: J'ai appliqué toutes les suggestions mentionnées ci-dessous et malheureusement aucune ne fonctionne jusqu'à présent (mon AsyncTask
ne démarre toujours pas).
Et une autre question: utiliser plus d'un AsyncTask
dans la même activité a quelque chose à voir avec mon problème?
Puisque (je suppose) aucune des autres solutions suggérées ne fonctionne, je soupçonne que votre problème réside dans la façon dont les AsyncTask
sont exécutés. Si plusieurs AsyncTasks s'exécutent dans la même activité, comme dans votre application, ces AsyncTasks ne s'exécuteront pas en parallèle. Ils s'exécuteront l'un après l'autre.
Je soupçonne que vos autres tâches AsyncTask sont longues, de sorte que votre GetDataJSON
AsyncTask attend la fin des autres tâches.
La solution consiste à activer l'exécution parallèle d'AsyncTask. Utilisez le code suivant pour exécuter AsyncTasks en parallèle.
GetDataJSON g = new GetDataJSON();
g.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
Depuis les documents AsyncTask:
Ordre d'exécution
Lors de leur introduction, les tâches AsyncTasks ont été exécutées en série sur un seul thread d'arrière-plan. À partir de DONUT, cela a été changé en un pool de threads permettant à plusieurs tâches de fonctionner en parallèle. À partir de HONEYCOMB, les tâches sont exécutées sur un seul thread pour éviter les erreurs d'application courantes causées par l'exécution parallèle.
Si vous voulez vraiment une exécution parallèle, vous pouvez appeler executeOnExecutor (Java.util.concurrent.Executor, Object []) avec THREAD_POOL_EXECUTOR.
J'espère que cela t'aides.
il suffit de changer vos paramètres asynctask
class GetDataJSON extends AsyncTask<String, Void, String>
à,
class GetDataJSON extends AsyncTask<Void, Void, String>
À partir de votre question, j'ai conclu que vous essayez d'obtenir la liste d'amis du serveur et en fonction du résultat, vous afficherez le message Toast.
Selon votre code, vous ne créez pas et n'affichez pas le AlertDialog à partir de alertDialogBuilder. Essayez d'afficher la AlertBox.
Comme AsyncTask s'exécute dans un thread séparé. D'où le
if (friends.contains(friend))
s'exécutera immédiatement après
g.execute();
Ainsi, même l'utilisateur est dans la liste d'amis, il affichera le Toast de la partie else.
De plus, vous n'avez pas mis les journaux dans les méthodes Asynctask, cela pourrait vous donner l'impression qu'AsyncTask n'est pas en cours d'exécution.
Je vous suggère de déplacer votre code de condition if
de AlertDialog
vers onPostExecute()
méthode de la GetDataJSON
et de le mettre après showList2();
. Mettez également quelques journaux dans les méthodes AsyncTask.
J'espère que cela vous aidera. Veuillez trouver le code ci-dessous pour votre référence:
public class AIssue extends Activity {
String result = " DATA";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.some);
findViewById(R.id.button1).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View arg0) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
AIssue.this);
alertDialogBuilder.setCancelable(false);
alertDialogBuilder.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
GetDataJSON g = new GetDataJSON();
g.execute();
}
});
alertDialogBuilder.create().show();
}
});
}
// Getting the users
private class GetDataJSON extends AsyncTask<Void, Void, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.e("IN", "ONPRE EXECUTE");
}
@Override
protected String doInBackground(Void... params) {
String result = "SOME DATA";
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
Log.e("IN", "DO IN BACKGROUND");
} catch (InterruptedException e) {
e.printStackTrace();
result = "ERROR";
}
}
return result;
}
@Override
protected void onPostExecute(String result) {
Log.e("IN", "ON POST EXECUTE");
Log.e("IN", "" + result);
/*****
* Your Condition to Check The Friend should be here after
* showList2();
* ***/
if (result.equalsIgnoreCase("SOME DATA"))// replace it with your
// condition to check
// friends
{
Log.e("IN", "IF");
} else {
Log.e("IN", "ELSE");
}
}
}
}
Dans la méthode getData2 (), essayez ceci:
new AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
// your code
}
@Override
protected void onPostExecute(String result){
// your code
}
}.execute();
ou si cela ne fonctionne pas, mettez la classe AsyncTask en dehors de la méthode, puis passez directement un appel pour exécuter la classe AsyncTask au lieu de getData2 (), comme ceci
new GetDataJSON().execute();
ajoutez cette méthode de remplacement dans la tâche Aysc.
@Override
protected void onPreExecute() {
super.onPreExecute();
}
Je ne sais pas ce que vous essayez de faire ici, mais ce code s'exécutera avant la fin de la tâche asynchrone.
if (friends.contains(friend)) // if you are already friends with that user
Toast.makeText(getApplicationContext(), "You are already friends with that user!",
Toast.LENGTH_LONG).show();
else {
if (!users.contains(friend)) // the user doesn't exist in our database
Toast.makeText(getApplicationContext(), "That user doesn't exist! You either haven't introduced the right email or he's not a registered user within Poinder.",
Toast.LENGTH_LONG).show();
else // the user exists so we add him to the friends list
{
//do something
}
Si vous voulez que ce code s'exécute après la fin de votre tâche asyc, ajoutez ce code dans la méthode ur showList2 ().
Au fait, pourquoi créer une tâche asynchrone dans la méthode interne. C'est une mauvaise idée. Créez une tâche aynch distincte. afin que vous puissiez utiliser d'une autre activité.
Je ne pense pas que forcer le mode strict aide dans cette situation. Vous devez utiliser AsyncTask au lieu du mode strict lors du codage des opérations réseau (comme celles que vous faites dans la méthode doInBackground) afin que votre interface utilisateur ne soit pas bloquée.
Le mode strict force l'exécution des opérations sur le thread principal de l'application, tandis que AsyncTask s'exécute sur un thread d'arrière-plan.
Ajouter un constructeur sur AsyncTask
public GetDataJSON (){
}
Ajoutez son onPreExecute pour être plus sûr
@Override
protected void onPreExecute() {
super.onPreExecute();
Toast.makeText(this /*or getActivity()*/,"IT'S WORKING!!!", Toast.LENGTH_LONG).show();
}
Le problème vient de vos paramètres asynctask
La documentation de Google Android indique que:
Une tâche asynchrone est définie par 3 types génériques, appelés Params, Progression et Résultat, et 4 étapes, appelées onPreExecute, doInBackground, onProgressUpdate et onPostExecute.
Types génériques d'AsyncTask:
Les trois types utilisés par une tâche asynchrone sont les suivants:
La documentation de Google Android indique que:
Types génériques d'AsyncTask:
Les trois types utilisés par une tâche asynchrone sont les suivants:
Tous les types ne sont pas toujours utilisés par une tâche asynchrone. Pour marquer un type comme inutilisé, utilisez simplement le type Void:
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
Donc, comme vous n'envoyez aucun paramètre à la tâche AsyncTask, faites votre tâche asynchrone comme ci-dessous
// Getting the users
public void getData2(){
new GetDataJSON().execute();
}
class GetDataJSON extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
/// your logic here
return result;
}
@Override
protected void onPostExecute(String result){
// your logic here
}
}
Une solution à ce problème, assez habituelle, que j'ai introduite dans mon développement actuel est AsyncService, je n'utiliserai pas toutes les fonctionnalités de cette bibliothèque (le système Ache) mais elle est puissante et elle vous aide également à nettoyer le code dans vos activités.
Je ne sais pas s'il existe une autre solution qui aide les développeurs à séparer les préoccupations et à nettoyer le code (en Android je veux dire) comme ça, c'est le meilleur que j'ai essayé et peut-être devriez-vous lui donner un essayez aussi. Cela vous aidera à résoudre votre problème actuel.
J'espère que cela aide.