8

在android中,我正在为url连接创建线程。在线程内部,我将响应消息存储在一个全局声明的字符串中。当我访问方法方法时,它返回null。

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

8 回答 8

5

你真的只想使用它Thread,试试这个

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

    }
}
于 2013-03-13T08:11:07.333 回答
2

您错过了使用线程的全部意义,因为我们使用它们在单独的线程中执行昂贵或可能很长时间的操作,以免阻塞 UI 线程。因此,您不能启动线程并期望立即获得结果,因为 Premsuraj 会在线程完成之前返回。

正如其他人所建议的,更简洁的方法是使用 AsyncTask,它将过程封装在三个主要阶段:OnPreExecute、doInBackground 和 onPostExecute,它们的名称是不言自明的,第一个执行您可能需要的任何初始化,第二个实际做异步工作,第三个用于处理整个操作的结果。

这是一个简单的示例,当然它可以改进,但应该可以帮助您理解它:

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

}

希望能帮助到你。

于 2013-03-13T08:03:04.823 回答
2

您获得的值为resultnull ,因为该方法rate正在运行一个线程,因此return不等待完成该线程。

您可以使用以下技术之一来解决问题

  • 处理程序
  • 异步。任务

您也可以查看链接以供参考。

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

于 2013-03-13T08:13:13.190 回答
1

可能您可以将主/当前线程/类的引用传递给线程。并且线程会将其结果存储在该引用对象中。

下面是一个简单的例子。

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

}
于 2013-03-13T09:07:53.260 回答
0

只需声明一个类变量并在您的线程中传递对象

于 2013-03-13T07:43:40.637 回答
0

您不能从线程返回值。您的函数 Rate_fetch 将在线程开始执行之前返回。一种解决方案是使用 AsyncTask 并使用其 onPostExecute 中的值。

于 2013-03-13T07:44:47.680 回答
0

如果您选择使用单独的线程来执行您的逻辑,则暗示线程内部代码的执行将是异步的,因此您无法立即访问结果而忽略异步线程执行。您应该考虑使用类似http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/FutureTask.html

于 2013-03-13T07:49:50.503 回答
0

看看Thread Local,它让你携带一个参数,线程是它自己的局部变量。

于 2013-03-13T08:57:04.493 回答