Android - возвращает логическое значение из потока

Я пытаюсь вернуть boolean значение из runnable метод в пределах Thread, Мне нужно знать, является ли HTTPRequest метод удался или нет. Проблема в том, что я знаю, что запрос выполнен успешно, но я всегда получаю false как ответ.


public boolean SmsDelivery;

SmsDelivery=sendSMS(prefix, number);

 if(SmsDelivery){
    //Do stuff
}
//The method itself
    private boolean sendSMSinThread(final String str){
        final AtomicBoolean b = new AtomicBoolean(false);
        Thread thread = new Thread(new Runnable(){

            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(str);
            @Override
            public void run() {
                try {
                    // Execute HTTP Post Request
                    //HttpResponse response = httpclient.execute(httppost);
                    httpclient.execute(httppost);
                    b.set(true);
                } catch (ClientProtocolException e) {
                    // TODO Auto-generated catch block
                    Log.e("Thread:","Unable to generate call"+e);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    Log.e("Thread:","Unable to generate call"+e);
                }
            }
        });
        thread.start();
        return b.get();
    }


ОБНОВИТЬ

На основании приведенных здесь советов мне удалось получить желаемый результат, однако я не знаю, какой метод больше подходит для моих нужд. Может ли кто-нибудь порекомендовать, как лучше использовать в моем случае? С помощью AsyncTask или Thread + join метод.
Первый метод использует AsyncTask следующим образом:

SmsTask smsTask = new SmsTask();
        try{
            smsResult = smsTask.execute(urlString).get();
        }catch (InterruptedException e){
            e.printStackTrace();
        }catch (ExecutionException e){
            e.printStackTrace();
        }

//the class itself
     class SmsTask extends AsyncTask<String,Void, Boolean> {
         final AtomicBoolean b = new AtomicBoolean(false);

        @Override
        protected Boolean doInBackground(String... params) {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(params[0]);

            try {
                httpclient.execute(httppost);
                b.set(true);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return b.get();
        }

        @Override
        protected void onPostExecute(Boolean result) {
            // result holds what you return from doInBackground
            Log.i("result from async: ",""+result);
            super.onPostExecute(result);
        }
    }


Второй метод, почти такой же, как я публиковал, но с методом thread.join():

thread.start();
try {
    thread.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}
return b.get();

4 ответа

Вам следует подождать, пока задача не будет выполнена. В этом случае вы должны запустить этот код в одном потоке (новый поток бесполезен) или использовать Android AsyncTaskкак класс и процесс в результате onPostExecute метод.

Есть несколько способов достичь этого.

  1. Используйте callable вместо runnable, так как метод вызова callable может вернуть результат
  2. Придерживайтесь вашего подхода, но прежде чем возвращать результат, вызовите thread.join()

    thread.start();
    thread.join();
    return b.get();
    

    Недостатки

    Если будут отправлены тысячи SMS, они создадут столько потоков. Здесь нет смысла создавать поток, так как вы можете сам входящий поток отправлять SMS.

  3. Используйте Runnable и Future.

    а. Для каждого SMS создайте объект SendSms,

    б. Это создаст максимум 10 потоков.

    с. Отправка SMS и getSMSdelivery будут синхронными событиями. Таким образом, для каждого отправленного SMS вы можете получить статус доставки, если это ваше требование.

    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    public class SendSms 
    {
        private static ExecutorService pool = Executors.newFixedThreadPool(10);
    
       public boolean submitSms(String message,String phNo)
       {        
          Runnable run = new SendSMSThread(message,phNo);
          Future future = pool.submit(run);
          try {
              if(null ==future.get())
              {
                  return true;
              }
          } catch (InterruptedException | ExecutionException e) {
              // SMS Sending failed.
              e.printStackTrace();
             return false;
          }
        return false;
        }
    
       private class SendSMSThread implements Runnable
       {
           String message;
           String phNo;
           public SendSMSThread(String message,String phNo)
           {
               this.message = message;
               this.phNo = phNo;
           }
           public void run()
           {
               //Send SMS
           }
        }
    }
    
  4. Все вышеперечисленные три решения являются блокирующими. Таким образом, он будет держать потоки в состоянии BLOCKING, тем самым создавая значительную угрозу для масштабируемости системы.

    а. Используйте BlockingQueue.

    б. Для каждого запроса SMS добавьте объект SMSObject в BlockingQueue.

    с. Используйте пул потоков и обрабатывайте объекты в очереди.

    д. Как только SMS успешно отправлено, сохраните результат в другой структуре данных.

    е. Используйте пул потоков, прочитайте данные из вышеупомянутой структуры данных и оповестите об успешной доставке SMS.

Вы можете использовать какой-нибудь шаблон Observer или что-то в этом роде.

Что-то вроде этого:

// есть пользовательский Runnable

public class HTTPRequestRunnable implements Runnable {

    HttpClient httpclient;
    HttpPost httppost;
    private HTTPRequestListner listner;

    public HTTPRequestRunnable(String str, HTTPRequestListner listner) {
        httpclient = new DefaultHttpClient();
        httppost = new HttpPost(str);
        this.listner = listner;

    }
    @Override
    public void run() {
        try {
            // Execute HTTP Post Request
            //HttpResponse response = httpclient.execute(httppost);
            httpclient.execute(httppost);
            if (listner != null)
                listner.onSuccess();
        } catch (ClientProtocolException e) {
            if (listner != null)
                listner.onFail();
            Log.e("Thread:", "Unable to generate call" + e);
        } catch (IOException e) {
            if (listner != null)
                listner.onFail();
            e.printStackTrace();
            Log.e("Thread:", "Unable to generate call" + e);
        }
    }


    public void setListner(HTTPRequestListner listner) {
        this.listner = listner;
    }
    /**
     * here is your observer class
     */

    public interface HTTPRequestListner {

        void onSuccess();

        void onFail();
    }
}

Затем используйте это в своем методе:

public void sendSMSinThread(final String str){

        HTTPRequestRunnable httpRequestRunnable = new HTTPRequestRunnable(str,new HTTPRequestListner() {
            @Override
            public void onSuccess() {
                //DO your logic here on success
            }

            @Override
            public void onFail() {
               //DO your logic here on fail
            }
        });

        Thread thread = new Thread(httpRequestRunnable);
        thread.start();
    }

Вот и ты, и я надеюсь, что это поможет вам

Попробуй это

thread.start();
thread.join();
return b.get();
Другие вопросы по тегам