-1

I want to make my code wait until there is a change anywhere in my class to the variable finaloutcomes. Is there any way to do this? I am carrying this out within an Asynctask, which I posted below.

 public HashMap<String,String> checkbetoutcome() {

    new LoadAllGamet().execute();

    // INSERT CODE HERE

    return finaloutcomes;

}

ASYNCTASK

class LoadAllGamet extends AsyncTask<String, String, String> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();

        }

        protected String doInBackground(String... args) {
           // HttpParams httpParameters = new BasicHttpParams();
           // HttpConnectionParams.setConnectionTimeout(httpParameters, 250000);
            //HttpConnectionParams.setSoTimeout(httpParameters, 250000);
            HttpClient client = new DefaultHttpClient();
            HttpPost post = new HttpPost(url_check_bet);
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("param", bet));
           // Log.d("CURRENTITEM", currentitem);
            try {
                post.setEntity(new UrlEncodedFormEntity(params));
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
            try {
                HttpResponse response = client.execute(post);
                Log.d("Http Post Responsecxxx:", response.toString());
                HttpEntity httpEntity = response.getEntity();
                InputStream is = httpEntity.getContent();
                JSONObject jObj = null;
                String json = "";
                client.getConnectionManager().closeExpiredConnections();
                try {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(
                            is, "iso-8859-1"), 8);
                    StringBuilder sb = new StringBuilder();
                    String line = null;
                    while ((line = reader.readLine()) != null) {

                        if (!line.startsWith("<", 0)) {
                            if (!line.startsWith("(", 0)) {
                                sb.append(line + "\n");
                            }
                        }
                    }

                    is.close();
                    json = sb.toString();

                    json = json.substring(json.indexOf('{'));
                //    Log.d("sbsssssssssss", json);
                    try {
                        jObj = new JSONObject(json);
                    } catch (JSONException e) {
                        Log.e("JSON Parser", "Error parsing data " + e.toString());
                    }
                    allgames = jObj.getJSONArray("bets");
                 //   Log.d("WHAT IS MY ARRAY?", allgames.toString());

                       for (Integer i = 0; i < allgames.length(); i++) {
                           HashMap<String,String> statuses = new HashMap<>();
                            JSONObject c = allgames.getJSONObject(i);
                            JSONArray currentbet = c.getJSONArray("bet");
                            Log.d("Single array",currentbet.toString());

                           //  Storing each json item in variable

                           for (Integer a = 0; a < currentbet.length();a++) {
                               JSONObject d = currentbet.getJSONObject(a);
                            String Result = d.getString("Result");
                               String id = d.getString("gid");
                            Log.d("RESULTS",Result);

                           statuses.put(id, Result);
                        }
                           allbetsmap.add(i, statuses);
                           Log.d("ddd", statuses.toString());
                           Log.d("AAA", allbetsmap.get(i).toString());


                       }



                    } catch (Exception e) {
                        Log.e("Buffer Error", "Error converting result " + e.toString());
                    }


                }
             catch (IOException e) {
                e.printStackTrace();
            }




            return "";
        }



        @Override
        protected void onPostExecute(String param) {
            Log.d("SIZE",Integer.toString(allbetsmap.size()));
            //ArrayList<Map<String,String>> allbetsmap = new ArrayList<>();
            //ArrayList<Map<String,String>> passtocheck = new ArrayList<>();

            if (allbetsmap.size() == passtocheck.size()) {
                for (int i = 0; i < allbetsmap.size();i++) {
                if (allbetsmap.get(i).size() == passtocheck.get(i).size()) {
                    String finaloutcome = "won";
                    for (String a : allbetsmap.get(i).keySet()) {
                        String f = allbetsmap.get(i).get(a);
                        if(f.equals("null")) {
                            finaloutcome = "open";
                        }
                        else if (! (f.equals(passtocheck.get(i).get(a)))) {
                            finaloutcome = "lost";
                            break;
                        }
                    }
                    finaloutcomes.put(Integer.toString(i),finaloutcome);
                }
                }

            }
            Log.d("Vital",finaloutcomes.toString());


        }


    }
Alk
  • 5,215
  • 8
  • 47
  • 116
  • I think you nedd to a listener. May be this question will help you. http://stackoverflow.com/questions/994840/how-to-create-our-own-listener-interface-in-android – Cüneyt Jun 04 '15 at 21:13
  • I tried doing `private boolean value = false;` in my variable initiations and then right after finaloutcomes changes, I put `value = true'` and then did `while (! value) { Thread.sleep(1000);}` however it just made my app wait without finishing the execution ever – Alk Jun 04 '15 at 21:15
  • 1
    Change the way you are thinking, _notify_ the waiting thread that things have changed. – Boris the Spider Jun 04 '15 at 21:16
  • @BoristheSpider I'm really new to multi-threading, can you briefly explain how I would do that? – Alk Jun 04 '15 at 21:17
  • Try using Google and looking at the Java documentation. Look up listeners, and search about semaphores. – mbomb007 Jun 04 '15 at 21:24
  • Consider using `java.util.concurrent.CountDownLatch` to signal from one thread and wait for the signal in another. An example is provided in the documentation. You're interested in the latch referenced by `doneSignal`. – Andy Thomas Jun 04 '15 at 21:34
  • LoadAllGamet() is an AsyncTask if that helps, I'm assigning the value of finaloutcomes in the onpostexecute method and I need to pass it to the class which calls this one – Alk Jun 04 '15 at 21:38

1 Answers1

2

Ok, forget what I wrote before. I didn't realize you were writing code for android. Here is an improved version of LoadAllGamet. There are two important things here. 1. define as much as possible locally i.e. inside a method or - if that's not possible - inside the class. 2. return the result instead of putting it into some variable.

class LoadAllGamet extends AsyncTask<String, Void, HashMap<String,String>> {
    protected HashMap<String,String> doInBackground(String ... args) {
        HashMap<String,String> finaloutcomes = new HashMap<>(),
        HashMap<Integer, HashMap<String,String>> allbetsmap = new HashMap<>();

        HttpClient client = new DefaultHttpClient();
        ...
        Log.d("SIZE",Integer.toString(allbetsmap.size()));
        if (allbetsmap.size() == passtocheck.size()) {
          ...
        }
        Log.d("Vital",finaloutcomes.toString());
        return finaloutcomes;
    }
}

Whenever you want to do something that might take some time you should not run that in the UI thread of you App since it can block your UI. Instead run it asynchronously. One way of doing this is to use AsyncTask. Let's assume you want to do something and while that something is being processed you also want to update the UI (e.g. progress bars) from time to time. And once you are finished you want to do something else with the result. Here is one way of writing this.

void doSomething() {
  new AsyncTask<String, Progress, Result>() {
    protected Result doInBackground(String... args) {
      //some code
      publishProgress(values);
      //some more code
      return result;
    }

    protected void onProgressUpdate(Progress ... values) {
      updateProgessBars(values);
    }

    protected void onPostExecute(Result result) {
      doSomethingElse(result);
    }
  }.execute();
}

The String in new AsyncTask<String, Progress, Result> is the type of the arguments to doInBackground. Often however you don't really need that unless you want to pass arguments into execute. Progress is the type of the values you want to send to onProgressUpdate. That one you only need if you want to update your UI while the background processing is still going on. Result is of course your result type. Whatever you want to happen after the doInBackground is finished you write into onPostExecute.

Tesseract
  • 8,049
  • 2
  • 20
  • 37
  • If I write `return new LoadAllGamet().execute().get();` what changes would I have to make in my AsyncTask so that the hashmap is returned. I posted the asynctask above – Alk Jun 04 '15 at 21:53
  • I added another example. But why do you need to run that code in another thread anyway. It seems pointless since you never do more than one thing at a time. – Tesseract Jun 04 '15 at 22:20
  • I've seen in a lot of questions on here of the form `how to assign global variable in onpostexecute method of asynctask` the answer to use execute().get(), however after I tried it I still end up with an empty variable. What I'm trying to do now is something like this, it may seem trivial but I think it should work. ` finaloutcomes.put("dummy","dummy");` and then in my onpostexecute() ` finaloutcomes.remove("dummy"); ` and then ` while (finaloutcomes.containsKey("dummy")) { Thread.sleep(1000); }` – Alk Jun 04 '15 at 22:30
  • I noticed my previous answer didn't really fit in your case since you are writing an android app. So I gave you another example. – Tesseract Jun 04 '15 at 22:59
  • what I did is moved the whole if statement to the doinBackground() method and used the execute().get() idea... I know it's not recommended and I had to delete all my progress dialogs because it made them freeze, but it works... I will look at your solution though later on in development when I have most of the app done and I want to improve all the buggy areas. :) Thanks for your help – Alk Jun 04 '15 at 23:01
  • If it makes your progress dialogs freeze then you are calling `execute().get() ` on the UI thread. Don't do that. – Tesseract Jun 04 '15 at 23:04
  • How do I avoid doing that? – Alk Jun 04 '15 at 23:13
  • 1
    You can do that by using `onPostExecute` instead of pausing the thread and waiting for the result. See my edit. – Tesseract Jun 04 '15 at 23:34