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
метод.
Есть несколько способов достичь этого.
- Используйте callable вместо runnable, так как метод вызова callable может вернуть результат
Придерживайтесь вашего подхода, но прежде чем возвращать результат, вызовите thread.join()
thread.start(); thread.join(); return b.get();
Недостатки
Если будут отправлены тысячи SMS, они создадут столько потоков. Здесь нет смысла создавать поток, так как вы можете сам входящий поток отправлять SMS.
Используйте 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 } } }
Все вышеперечисленные три решения являются блокирующими. Таким образом, он будет держать потоки в состоянии 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();
}
Вот и ты, и я надеюсь, что это поможет вам