2013-03-13 14 views
5

W Android utworzę wątek dla połączenia URL. Wewnątrz wątku przechowuję komunikat odpowiedzi w ciągu znaków, który jest deklarowany globalnie. Kiedy uzyskam dostęp do metody method, zwróci ona wartość null.Jak zwrócić wartość z wątku w java?

public class Rate_fetch { 
     String total=""; 
      public String rate(String dt) 
     { 
    new Thread(new Runnable(){ 

     public void run(){ 


      try { 

      URL url = new URL(tally_ipaddr+"/prorate.jsp?plist="+sss.toString().trim()); 

      HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); 
      InputStream in = new BufferedInputStream(urlConnection.getInputStream()); 
      BufferedReader r = new BufferedReader(new InputStreamReader(in)); 
      String x = ""; 
      String total = ""; 
      x = r.readLine(); 
      int i=0; 

      while(x.length()>1) 
      { 
       total=total+x.toString().trim(); 
       i++; 
       x = r.readLine(); 
      } 
      } 
      catch(Exception e){ 
      return e.toString(); 
      } 
     }  

    }).start(); 

    return total; 



} 

Po wywołaniu metody zwraca wartość null.

Rate_fetch rf=new Rate_fetch(); 
     String amt= rf.rate(prodList); 
+0

AsyncTask byłby czystszym sposobem na zrobienie tego. – Swayam

+0

Możesz śledzić pole o nazwie total ze zmienną lokalną o tej samej nazwie. – flup

+0

Ram znalazłeś jakieś rozwiązanie dla powyższego pytania, utknąłem z tym samym problemem. –

Odpowiedz

3

To naprawdę chcesz użyć Thread tylko, spróbuj tego

public class Rate_fetch { 
    String total = ""; 
    boolean b = true; 

    public String rate(String dt) { 
     StringBuilder sb = new StringBuilder(); 
     new Thread(new Runnable() { 

      public void run() { 

       try { 

        URL url = new URL(tally_ipaddr + "/prorate.jsp?plist=" 
          + sss.toString().trim()); 

        HttpURLConnection urlConnection = (HttpURLConnection) url 
          .openConnection(); 
        InputStream in = new BufferedInputStream(urlConnection 
          .getInputStream()); 
        BufferedReader r = new BufferedReader(
          new InputStreamReader(in)); 
        StringBuilder sb = new StringBuilder(); 
        String s; 
        while (true) { 
         s = r.readLine(); 
         if (s == null || s.length() == 0) 
          break; 
         sb.append(s); 
        } 
        b = true; 
       } catch (Exception e) { 
        b = true; 
       } 
      } 

     }).start(); 
     while (b) { 

     } 
     total = sb.toString(); 
     return sb.toString(); 

    } 
} 
+0

To jest bardzo hacky, nie podoba mi się to. Poza tym to nie zadziała, odkąd zainicjowałeś swoją wartość logiczną "true". W każdym razie, gdyby naprawdę chciał użyć Nici, a NIC NIE INNEGO, chciałbym zapisać odniesienie do Aktywności, a następnie użyć Handlerów, aby ją zaktualizować. – Areks

+3

Po chwili (b) pętla {} zabija punkt używania oddzielnego wątku. –

+0

ten kod działa, ale nie zwraca żadnej wartości z metody. Zmienna globalna ma wynik. –

0

Wystarczy zadeklarować zmienną klasy i passe obiekt w wątku

+0

Dlaczego miałby otrzymać ciąg znaków i nie robić nic innego poza zapisaniem odniesienia? Najprawdopodobniej będzie z nim pracował, zapisanie referencji nie rozpocznie procesu. – Areks

0

Nie można zwrócić wartość z wątku. Twoja funkcja Rate_fetch powróciłaby przed uruchomieniem wątku. Rozwiązaniem jest użycie AsyncTask i użycie wartości w jego onPostExecute.

1

Brakuje ci całego punktu użycia nici, ponieważ używamy ich do wykonania kosztownej lub potencjalnie długiej operacji w osobnym wątku, aby nie blokować wątku interfejsu użytkownika. Dlatego nie można uruchomić wątku i oczekiwać natychmiastowego uzyskania wyniku, ponieważ Premsuraj zwraca go przed zakończeniem wątku.

Zgodnie z sugestią innych osób czystszym sposobem na to byłoby użycie AsyncTask, który hermetyzuje proces w trzech głównych etapach: OnPreExecute, doInBackground i onPostExecute, ich nazwy są oczywiste, pierwsza inicjalizacja może potrzebna, druga faktycznie wykonuje pracę asynchroniczną, a trzecia służy do poradzenia sobie z wynikiem całej operacji.

Oto jeden krótki przykład, oczywiście można go poprawić, ale powinien pomóc go zrozumieć:

Rate_fetch

Twój samej klasy, ale bez wątków:

public class Rate_fetch { 

     public String rate(String dt) 
     { 
      String total=""; 
      try { 

       URL url = new URL(tally_ipaddr+"/prorate.jsp?plist="+sss.toString().trim()); 

       HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); 
       InputStream in = new BufferedInputStream(urlConnection.getInputStream()); 
       BufferedReader r = new BufferedReader(new InputStreamReader(in)); 
       String x = ""; 
       String total = ""; 
       x = r.readLine(); 
       int i=0; 

       while(x.length()>1) 
       { 
        total=total+x.toString().trim(); 
        i++; 
        x = r.readLine(); 
       } 
      } 
      catch(Exception e){ 
       return e.toString(); 
      }; 

      return total; 
     } 

    } 

Przykładem aktywność:

public class YourActivity extends Activity { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.layout); 

     GetRate asyncRate = new GetRate(); 
     asyncRate.execute(); // starting the task, can be done wherever you need, for example a Button click event 
    } 

    private class GetRate extends AsyncTask<Void, Integer, String> { 

     @Override 
     protected String doInBackground(Void... params) { 

      Rate_fetch fetch = new Rate_fetch(); 
      string rate = fetch.rate(); 

      return rate; 
     } 

     @Override 
     protected void onPostExecute(String rate) {      
      // Do whatever you need with the string, you can update your UI from here 
     } 
    } 

} 

Mam nadzieję, że to pomaga.

+1

Bez gwintowania nie można pracować w sieci, ponieważ dałoby to "NetworkOnMainThreadException" –

+1

Ale nie robimy tego, jest wykonywane w metodzie doInBackground, spróbuj sam. DoInBackground NIE jest MainThread, AsyncTask zawiera zarówno wątki, jak i aktualizację MainThread za pośrednictwem Handlerów, o ile wiem, ale mogę się mylić. – Areks

+0

Jak mogę uzyskać ciąg stawki w mojej działalności ?. –

0

przyjrzeć Thread Local, to sprawia, że ​​można nosić parametr wątek bycia własnym zmienna lokalna.

0

Prawdopodobnie możesz przekazać odniesienie do głównego/bieżącego wątku/klasy do wątku. a wątek zapisze wynik w tym obiekcie przywoływanym.

Poniżej znajduje się prosty przykład.

class CallerTest{ 
private ResultData result; // any data that you want from thread 

public void caller() throws Exception{ 
    ThreadClass thread = new ThreadClass(this); 
    thread.start(); 

    //wait for thread to finish 
    thread.join(); 

    //now you have data in >> this.result 
} 

public void setResult(ResultData rd){ 
    this.result = rd; 
} 
} 

class ThreadClass extends Thread{ 
    CallerTest cl; 
    public ThreadClass(CallerTest cl){ 
     this.cl = cl; 
    } 
    public void run() { 
    ResultData rd; 
    rd = //do code to retrive result 
    cl.setResult(rd); 
    } 

} 
Powiązane problemy