在unnested线程类

时间:2015-06-14 07:51:23

标签: java android

我编写了一些代码,在单独的线程中建立连接并检索一些数据。这一切都很好。

当我尝试通过Handler将此信息传回主线程时,我的问题就出现了。

因为离开主线程的线程的代码没有嵌套在主类中,所以传递给处理程序的引用似乎不成立。关于如何修改代码以允许将处理程序数据传递回主线程的建议。

主线程的代码(仅剥离重要位):

public class MyActivity extends Activity {

Handler mHandler = new Handler(){
    public void handleMessage(Message msg){
        Bundle b;
        if(msg.what==1){
            b = msg.getData();
            weCanMove = b.getBoolean("key");
            Log.d("what did we get", String.valueOf(b.getBoolean("key")));
        }
        super.handleMessage(msg);
    }
};

 public void start(View view) throws InterruptedException {
    Context context;
    Boolean weHaveFile = checkFile();
    System.out.println(userinfo[0] + "\n" + userinfo[1]);
    if (weHaveFile) {
        Intent intent = new Intent(MyActivity.this, OtherActivity.class);
        startActivity(intent);
    } else {

        //DatabaseMiddleMan login = new DatabaseMiddleMan();
        /*login.run();
        login.login(userinfo[0],userinfo[1]);*/
        ArrayList <String> uinfo = new ArrayList<String>();
        uinfo.add(0,userinfo[0]);
        uinfo.add(1,userinfo[1]);
        DatabaseMiddleMan login = new DatabaseMiddleMan(0,uinfo,this.mHandler);
        Thread thread = new Thread(login);
        thread.start();
        Thread.sleep();
        if(weCanMove) {
            Intent intent = new Intent(MyActivity.this, OtherActivity.class);
            startActivity(intent);
        }else{

            context = this.getApplicationContext();

            new AlertDialog.Builder(MyActivity.this)
                    .setTitle("Errore")
                    .setMessage("Credenziali errate!")
                    .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    })
                    .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            // do nothing
                        }
                    })
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .show();
        }
    }
}

在单独的线程中运行的对象的代码:

public class DatabaseMiddleMan implements Runnable{
public String serverAddress;
public boolean loginsucess = false;
private ArrayList<String> params;
private int whichMethodToExecute;
private Handler hd;

public DatabaseMiddleMan(int selection, ArrayList<String> params, Handler msg){
    this.params = params;
    this.whichMethodToExecute = selection;
    hd = msg;
}

public void run(){
    if(this.whichMethodToExecute ==  0){
        this.login();
    }
}
   public void login(){
    String username = params.get(0);
    String password = params.get(1);

    String link = "xxxxxxxxxxxxxx";
    String query = "xxxxxxxxxxxxxxx";
    HttpClient httpClient = new DefaultHttpClient();

    HttpPost httpPost = new HttpPost(link);

    BasicNameValuePair queryPair = new BasicNameValuePair("query", query);
    List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();
    nameValuePairList.add(queryPair);
    Bundle b = new Bundle(1);

    try {
        UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(nameValuePairList);

        httpPost.setEntity(urlEncodedFormEntity);
        try {
            HttpResponse httpResponse = httpClient.execute(httpPost);
            InputStream inputStream = httpResponse.getEntity().getContent();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String bufferedStrChunk = null;
            StringBuilder stringBuilder = new StringBuilder();

            while ((bufferedStrChunk = bufferedReader.readLine()) != null) {
                stringBuilder.append(bufferedStrChunk);
            }

            String queryResult = stringBuilder.toString();
            Log.d("SQL PASS",queryResult);
            if (queryResult.equals(password)){
                loginsucess = true;

                b.putBoolean("key",true);
                Log.d("SQL PASS","test passed");
            } else {

                b.putBoolean("key",false);
            }

        } catch (ClientProtocolException cpe) {
            System.out.println("First Exception caz of HttpResponese :" + cpe);
            cpe.printStackTrace();
        } catch (IOException ioe) {
            System.out.println("Second Exception caz of HttpResponse :" + ioe);
            ioe.printStackTrace();
        }
    } catch (UnsupportedEncodingException uee) {
        System.out.println("An Exception given because of UrlEncodedFormEntity argument :" + uee);
        uee.printStackTrace();
    }

    Message msgs = hd.obtainMessage();
    msgs.setData(b);
    hd.sendMessage(msgs);
}

1 个答案:

答案 0 :(得分:0)

消息循环器是什么?它是一个接收消息队列的对象,并在同一个线程中依次运行消息处理程序。接下来将在上一次完成后运行。

所以,想象一下,有一些启动事件被放入队列中。 looper启动一个处理程序,它将运行级联方法,最后启动 start(View view)。 Looper将暂停,直到所有方法都完成并且处理程序完成。因此,队列中的下一条消息(将运行您的处理程序的 handleMessage )只能在 start 返回后执行。

从不在主线程中使用 Thread.sleep()。最好使用

thread.join();

等待asyn线程完成。

如果你想在线程完成后在线程之间传递一个单个对象,你可以使用这种方法:

在Runnable中分配一些易变量:

public class DatabaseMiddleMan implements Runnable{

    public volatile Bundle mResult;
    ...

在线程完成后,您可以访问此变量:

    DatabaseMiddleMan login = new DatabaseMiddleMan(0,uinfo,this.mHandler);
    Thread thread = new Thread(login);
    thread.start();
    ...
    // blah blah blah, here doing some actions in parallel, while thread doing it's work
    ...
    thread.join();

    Bundle b = login.mResult;        
    weCanMove = b.getBoolean("key");

请注意,您可以在此处传递一个布尔值,而不是 Bundle 。此外,如果需要,您可以创建多个结果变量。