java - Android: Async Task : doInBackground returns before an action callback -
i using mqtt android application. implemented mqtt connection in class extending asynctask. code:
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 own action", snackbar.length_long) .setaction("action", null).show(); } }); context = getapplicationcontext(); mqtt mqtt = new mqtt(); mqtt.execute(); } @override public boolean oncreateoptionsmenu(menu menu) { // inflate menu; adds items action bar if present. getmenuinflater().inflate(r.menu.menu_main, menu); return true; } @override public boolean onoptionsitemselected(menuitem item) { // handle action bar item clicks here. action bar // automatically handle clicks on home/up button, long // specify 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) { // connected log.d(tag, "onsuccess"); status = "true"; } @override public void onfailure(imqtttoken asyncactiontoken, throwable exception) { // 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); } } }
the problem facing here doinbackground() returns before onsuccess called. because of this, function returns status null. tried take log of returned value in onpostexecute(), shows null. whereas assigning value of status in onsuccess function inside doinbackground. there way can make sure doinbackground returns after onsuccess completed.
quick solution block until async task finishes, e. g. using 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()` invoked in callback return status; }
Comments
Post a Comment