Java Question raiseEventFromDifferentThread

laguilar

Member
Licensed User
I am trying to raise an event from a Runnable class, but it does not seem to be working. My B4A subs never get hit. But inside the java library, it outputs the "Attempting to raiseevent..." which is after checking if the sub exists first. So it is detecting the sub, but not calling it for whatever reason.

Forgive me if something is not syntax-wise correct, I heavily modified this from our proprietary code so I could provide this example of my issue.

Here is my java code:

B4X:
    public void Validate(String postStr) {
        final List<BasicNameValuePair> nameValuePairs = new ArrayList<BasicNameValuePair>();
        nameValuePairs.add(new BasicNameValuePair("data", postStr));
        Runnable r = new Runnable() {
            public void run() {
                postData("https://www.dummydomain.com/api.php?f=validate", nameValuePairs);
            }
        };
        BA.submitRunnable(r, this, 0);
    }
   
    private void postData(String url, List<BasicNameValuePair> nameValuePairs) {
        if (BA.debugMode == true) { BA.Log("URL:" + url); }
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost(url);
        try {
            if (nameValuePairs != null) {
                httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                for (BasicNameValuePair pair : nameValuePairs) {
                    if (BA.debugMode == true) { BA.Log("NAME: " + pair.getName() + " => VALUE: " + pair.getValue()); }
                }
            }
            if (BA.debugMode == true) { BA.Log("execute..."); }
            HttpResponse response = httpclient.execute(httppost);
            if (BA.debugMode == true) { BA.Log("Read..."); }
            BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            String body = "";
            String line = "";
            while ((line = rd.readLine()) != null) {
                body = body + line;
            }
            if (BA.debugMode == true) { BA.Log("BODY:"+body); }
            if (url.contains("?f=validate") == true) {
                if (thisBA.subExists(thisEventName + "_validationresponse")) {
                    BA.Log("Attempting to raiseevent..." + thisEventName + "_validationresponse");
                    thisBA.raiseEventFromDifferentThread(MyDummyClass.this, MyDummyClass.this, 0, thisEventName + "_validationresponse", true, new Object[] { body });
                }
            } else if (url.contains("?f=otherrequest") == true) {
                if (thisBA.subExists(thisEventName + "_otherrequestresponse")) {
                    BA.Log("Attempting to raiseevent..." + thisEventName + "_otherrequestresponse");
                    thisBA.raiseEventFromDifferentThread(MyDummyClass.this, MyDummyClass.this, 0, thisEventName + "_otherrequestresponse", true, new Object[] { body });
                }
            }
            if (BA.debugMode == true) { BA.Log(body); }
        } catch (ClientProtocolException e) {
            if (thisBA.subExists(thisEventName + "_validationerror")) {
                BA.Log("Attempting to raiseevent..." + thisEventName + "_validationerror");
                thisBA.raiseEventFromDifferentThread(MyDummyClass.this, MyDummyClass.this, 0, thisEventName + "_validationerror", true, new Object[] { e.getMessage() });
            }
            if (BA.debugMode == true) { BA.Log(e.getMessage()); }
        } catch (IOException e) {
            if (thisBA.subExists(thisEventName + "_validationerror")) {
                BA.Log("Attempting to raiseevent..." + thisEventName + "_validationerror");
                thisBA.raiseEventFromDifferentThread(MyDummyClass.this, MyDummyClass.this, 0, thisEventName + "_validationerror", true, new Object[] { e.getMessage() });
            }
            if (BA.debugMode == true) { BA.Log(e.getMessage()); }
        }
    }

and my B4A Subs...


B4X:
Public Sub mydummyclass_validationresponse(data As String)
    Log(data)
End Sub

Public Sub mydummyclass_otherrequestresponse(data As String)
    Log(data)
End Sub
 
Last edited:

Lee Gillie CCP

Active Member
Licensed User
You didn't show us how your class was initialized from B4A. Also the ellipses in your predicate cut us off from seeing the actual full event name. Hopefully the event name passed to store in thisEventName is ALL lower case? This one tripped me up the other day, so thought I would mention it, since your post is not complete enough to confirm.

Also there is a sub-forum for library creators that is more appropriate to post to.
 

laguilar

Member
Licensed User
Here is my initialization. the eventName being passed in this example would be "mydummyclass". As I mentioned above, the call to subExists() returns true, so it is finding the sub, I'm assuming there is a signature discrepancy. And yes they are all lower-case, the eventName being passed, in the raiseevent calls, and the b4a sub names.

B4X:
private BA thisBA;
    private String thisEventName;
   
    public void Initialize(BA ba, String eventName) {
        thisBA = ba;
        thisEventName = eventName;
    }
 

laguilar

Member
Licensed User
Ok, so after some further investigation and fiddling around, I am finding that my b4a subs are now being hit. But I've encountered either a b4a limitation or a bug, I'm not sure which. While debugging, I am un-able to pause the debugger on a breakpoint within a b4a class. The code gets executed, I see it in the log, but in the IDE, it doesn't pause. I've double checked that it's in debug mode, not release. Any ideas?
 

Erel

B4X founder
Staff member
Licensed User
But I've encountered either a b4a limitation or a bug, I'm not sure which. While debugging, I am un-able to pause the debugger on a breakpoint within a b4a class.
Probably a bug in your library. Maybe you are raising an event from the wrong thread.

However you shouldn't create such library at all. This Java code is very bad and you can easily implement it with OkHttpUtils2.
 

laguilar

Member
Licensed User
It's part of a much larger java library that is private code with many other references, I posted only the essentials that I was encountering a problem with.

You say the java code is very bad? Could you point out what you mean? Besides the obvious temporary log lines.

Also, the issue with being able to pause the debugger seems intermittent. To test this over the course of today every debug run of my project I placed a breakpoint on the Activity_Create first line, sometimes it hit it, sometimes it doesn't. Between each debug run I've tried doing a "Clear Data" on the application, un-installing it, doing a clean of the project, restarting ADB, re-connecting the USB, and on 2 separate devices (ASUS Zenpad 3S tablet, and my HTC 10) both with very capable hardware.

One thing I can point out, I'm not sure if it matters or not, but I have around 2.5GB remaining on my SSD, my project after building is around 8MB. And one particular b4a class in my project stands at around 36k lines.

Besides my temporary 2.5GB space issue (I'm cloning to a larger SSD in the coming week), I am running an AMD-A10 cpu with 8GB of ram. Which I know is sufficient, I've run b4a on my old laptop with half the specs with no problems (Intel chip).
 

Erel

B4X founder
Staff member
Licensed User
You say the java code is very bad?
1. DefaultHttpClient was deprecated a long time ago.
2. Creating a new client for each request is a large waste.
3. You are reading the result inefficiently and building the result string inefficiently.
4. All of your code can be implemented in B4X directly and easily. It will be simpler to maintain and debug if you do it in the B4A code.
 

laguilar

Member
Licensed User
Ok, I'll look into a class that is not depreciated, though I don't see a problem with how the request is being built. Your referring to the namevaluepairs and the streams? I see no issue with the namevaluepairs, it seems to suite my needs very well. I do agree there is probably a more efficient way to read the response, I was following another example I found. And also as I mentioned above, this is part of a much larger .jar library that I am trying to consolidate as much into as I can so I can simply include that library in several other projects and go instead of having to make multiple copies of b4a classes/modules.

Any ideas about the debugger problem I am experiencing? As I mentioned above, I put a breakpoint on the first line into the Activity_Create and Activity_Resume sub routines and the IDE skips right past it, no breakpoints hit. And it seems intermittent, the only thing I have found to resolve it is disconnecting the usb cable from the device, closing the B4A IDE, and leaving it sit for 10-15 minutes, reconnect the usb, and start the IDE, and it usually works fine for the first build or two, then it happens again.
 
Top