2016-02-06 57 views
1

我正在为我的Android应用程序使用MQTT。我在扩展AsyncTask的类中实现了MQTT连接。这是我的代码:Android:异步任务:doInBackground在动作回调之前返回

public class MainActivity extends AppCompatActivity { 
    String TAG = "MQTT"; 
    private Context context; 
    String status; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 

     FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 
     fab.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 
         .setAction("Action", null).show(); 
      } 
     }); 
     context = getApplicationContext(); 
     MQTT mqtt = new MQTT(); 
     mqtt.execute(); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.menu_main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 

     //noinspection SimplifiableIfStatement 
     if (id == R.id.action_settings) { 
      return true; 
     } 

     return super.onOptionsItemSelected(item); 
    } 
    public class MQTT extends AsyncTask<String, Void, String> { 
     @Override 
     protected String doInBackground(String... params) { 
      String clientId = generateClientId(); 
      MqttAndroidClient client = 
        new MqttAndroidClient(context, "tcp://broker.hivemq.com:1883", 
          clientId); 

      try { 
       IMqttToken token = client.connect(); 
       token.setActionCallback(new IMqttActionListener() { 
        @Override 
        public void onSuccess(IMqttToken asyncActionToken) { 
         // We are connected 
         Log.d(TAG, "onSuccess"); 
         status = "True"; 
        } 

        @Override 
        public void onFailure(IMqttToken asyncActionToken, Throwable exception) { 
         // Something went wrong e.g. connection timeout or firewall problems 
         Log.d(TAG, "onFailure"); 
         status = "False"; 


        } 
       }); 
      } catch (MqttException e) { 
       e.printStackTrace(); 
      } 
      Log.d(TAG, "value of status " + status); 
      return status; 
     } 

     @Override 
     protected void onPostExecute(String s) { 
      super.onPostExecute(s); 
      Log.d(TAG, s); 


     } 
    } 
} 

我在这里面临的问题是doInBackground()在调用onSuccess之前返回。因此,此函数返回状态为空。我试图在onPostExecute()中获取返回值的日志,它显示为空。而我在doInBackGround中的onSuccess函数中分配状态值。有没有一种方法可以确保doInBackground只在onSuccess完成后才返回。

+1

您确定您需要一个AsyncTask吗? –

+0

在doInBackground中返回'token'。从onPostExecute设置动作回调 –

+0

谢谢@JyotmanSingh:我是Android新手。按照指导原则,网络相关任务在“异步任务”中很好。但是,你认为把这个放在onCreate中是个好主意吗? –

回答

3

快速解决方案是阻止,直到异步任务完成, G。通过使用Semaphore

protected String doInBackground(String... params) { 
    String clientId = generateClientId(); 
    MqttAndroidClient client = // ....     
    Semaphore s = new Semaphore(0); 
    try { 
     IMqttToken token = client.connect(); 
     token.setActionCallback(new IMqttActionListener() { 
      @Override 
      public void onSuccess() { 
       // ... 
       status = "True"; 
       s.release(); 
      } 

      @Override 
      public void onFailure() { 
       // ... 
       status = "False"; 
       s.release(); 
      } 
     }); 
    } catch (MqttException e) { 
     e.printStackTrace(); 
     s.release(); 
    } 
    s.acquire(); // blocks until `s.release()` is invoked in callback 
    return status; 
} 
+1

谢谢@Sasha。它解决了我的问题。 –

相关问题