2013-03-13 2 views
5

私はurl connection.Insideのスレッドを作成しています。グローバルに宣言されている文字列に応答メッセージを格納しています。メソッドメソッドにアクセスするとnullが返されます。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; 



} 

私がこのメソッドを呼び出すと、nullが返されます。

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

これを行うには、AsyncTaskが便利です。 – Swayam

+0

totalという名前のフィールドを、同じ名前のローカル変数でシャドウします。 – flup

+0

Ram上記の質問に対する解決策を見つけましたか?同じ問題を解決するためにplsの助けを借りてください。 –

答えて

3

それはあなたが本当にreturnは、スレッドを終了するために待機されていないので、この方法rateがスレッドを実行しているので、この

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

それは非常にハッキーだ、私はそれが好きではない。さらに、あなたがブール値を "true"で初期化してからは動作しません。とにかく、もし彼が本当にスレッドを使いたいと思っていて、それ以外のものがなければ、私はアクティビティへの参照を保存し、それを更新するためにハンドラを使います。 – Areks

+3

while(b){}ループは別のスレッドを使用する点を殺します。 –

+0

このコードは動作しますが、メソッドからの値は返しません。グローバル変数には結果があります。 –

0

ちょうどあなたがスレッドから値を返すことができないクラス変数を宣言して、スレッド

+0

なぜ彼は文字列を取得し、その参照を保存する以外の何もしませんでしたか?彼はおそらくそれを使って作業する必要があり、参照を保存するとプロセスが開始されません。 – Areks

0

でオブジェクトを時代遅れ。あなたの関数Rate_fetchはスレッドが実行を開始する前に戻ります。 解決策は、AsyncTaskを使用して、そのonPostExecuteの値を使用することです。

1

私たちはUIスレッドをブロックしないために別のスレッドで高価な操作や潜在的に長い操作を行うためにスレッドを使用しているため、その使用の全ポイントがありません。したがって、スレッドを開始することはできませんし、Premsurajのように即座に結果を得ることを期待して、スレッドが終了する前に戻ります。

他の人も示唆しているように、これを行うためのよりクリーンな方法は、AsyncTaskを使用することです。プロセスはOnPreExecute、doInBackground、onPostExecuteの3つの主要段階でカプセル化されます。 2番目は実際には非同期作業を行い、3番目は操作全体の結果を処理するために使用されます。

ここでは、もちろん、それを向上させることができるが、あなたがそれを理解するのに役立つはず、1つの簡単な例です:

Rate_fetch

あなたと同じクラスが、スレッドなし:

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; 
     } 

    } 

例アクティビティ:

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 
     } 
    } 

} 

希望します。

+1

スレッディングなしでは、 'NetworkOnMainThreadException'を与えるため、ネットワーク上で作業することはできません –

+1

しかし、私たちはそれをやっていません。doInBackgroundメソッドで実行されています。 doInBackgroundはMainThreadではありませんが、AsyncTaskはスレッディングとMainThreadの両方をハンドラを介して更新してカプセル化していますが、間違いかもしれません。 – Areks

+0

アクティビティでレート文字列を取得する方法は? –

2

あなたはヌルとしてresultの値を取得しているしてみてください、だけThreadを使用します。

あなたは問題に

  • ハンドラ
  • 非同期を解決するには、次の手法のいずれかを使用することができます。タスク

また、参照用のリンクも参照できます。

http://mobileorchard.com/android-app-developmentthreading-part-1-handlers/

0

Thread Localを見て、それはあなたがスレッドが独自のローカル変数であることでパラメータを運ぶことができます。

0

おそらく、メイン/現在のスレッド/クラスの参照をスレッドに渡すことができます。スレッドはその参照されたオブジェクトに結果を格納します。

以下は簡単な例です。

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); 
    } 

} 
関連する問題