GWT,如何使EntryPoint类等待AsyncCallback。

huangapple go评论58阅读模式
英文:

GWT, how to make EntryPoint class wait for AsyncCallBack

问题

我正试图使用GWT将一个Android应用程序转换成网站。这只是一个未来项目的想法。

我想做的是模仿Cursor功能。我可以通过创建一个类并模仿我想要使用的函数来做到这一点。

但是我遇到了一个问题:
我的用户界面在Cursor完全初始化之前就完成了其代码。

到目前为止,以下是它的工作原理。我在我的入口点的onModuleLoad中有以下代码:

Cursor cursor = databaseHelper.retrieveData("select * from '0-1'");
label.setText("Column-count: "+cursor.getColumnCount());

这会输出0,因为入口点在我的cursor类完全初始化之前不会等待。

我的retrieveData方法在这里:

Cursor retrieveData(String query){
    return new Cursor(query);
}

我的Cursor类中的构造函数在这里:

Cursor(String sql) {
    greetingService = GWT.create(GreetingService.class);
    columns = new ArrayList<>();
    rows = new ArrayList<>();
    currentPosition = -1;

    greetingService.greetServer(sql, new AsyncCallback<List<List<String>>>() {
        @Override
        public void onFailure(Throwable caught) {}

        @Override
        public void onSuccess(List<List<String>> result) {
            if (!result.isEmpty()) {
                columns = result.get(0);
                if (result.size() > 1) {
                    rows.addAll(result.subList(1, result.size()));
                }
            }
        }
    });
}

我尝试过使用while循环停止UI活动,等待一个布尔值从true变为false(在AsyncCallback的onSuccess中设置为false),但UI活动被锁定,网站崩溃。

有人在这方面有解决方案吗?

英文:

I am attempting to convert an android app to a website using GWT. This was just an idea for a future-project.

What I want to do is mimic the Cursor function. I can do that just fine creating a class and just mimicking the functions I want to use.

But here is my issue:
My UI finishes its code before the Cursor is fully initialized.

Here's how it works so far. I have the following code in my onModuleLoad, in my entrypoint:

Cursor cursor = databaseHelper.retrieveData(&quot;select * from &#39;0-1&#39;&quot;);
	label.setText(&quot;Column-count: &quot;+cursor.getColumnCount());

This outputs 0, because the entrypoint does not wait for my cursor-class to fully initialize.

My retrieveData method is here:

Cursor retrieveData(String query){
    return new Cursor(query);
}

And my constructor in the Cursor-class is here

Cursor(String sql) {
	greetingService = GWT.create(GreetingService.class);
	columns = new ArrayList&lt;&gt;();
	rows = new ArrayList&lt;&gt;();
	currentPosition = -1;
	
    greetingService.greetServer(sql, new AsyncCallback&lt;List&lt;List&lt;String&gt;&gt;&gt;() {
		@Override
		public void onFailure(Throwable caught) {}
		
		@Override
		public void onSuccess(List&lt;List&lt;String&gt;&gt; result) {
	    	if (!result.isEmpty()) {
				columns = result.get(0);
				if (result.size() &gt; 1) {
					rows.addAll(result.subList(1, result.size()));
				}
			}
		}
	});
}

I have tried stopping the UI-activity with a while-loop waiting for a boolean to go from true to false (set to false in the onSuccess of the AsyncCallback), but the UI-activity is just locked and the site crashes.

Does somebody have a solution here?

答案1

得分: 1

使用Promises

如果你正在向后端服务发起HTTP请求,你可以使用Fetch API,它使用了promises,尽管更多是方便而非必需。

GWT的Elemental2库提供了对promises和fetch API的绑定。例如:

DomGlobal.fetch("http://example.com/bar?x=5")
.then(response -> response.json())
.then(jsonData -> {
    parseDataAndUpdateUI(jsonData);
    return null;
});
英文:

Use Promises.

If you are making a HTTP request to a backend service, you could use the Fetch API, which uses promises, though convenient rather than necessary.

GWT's Elemental2 library provides bindings to the promises and fetch API's. For example:

DomGlobal.fetch(&quot;http://example.com/bar?x=5&quot;)
.then(response -&gt; response.json())
.then(jsonData -&gt; {
    parseDataAndUpdateUI(jsonData);
    return null;
});

答案2

得分: 1

做这些服务器调用的时候,你也可以使用 domino-rest,它已经有了 Android 实现 domino-rest-android,如果要进行多个调用并等待它们完成,你可以尝试使用 domino-aggregator

使用 domino-aggregator,你可以像下面这样做:

ContextAggregator.ContextWait<String> waitForString = ContextAggregator.ContextWait.create();
ContextAggregator.ContextWait<Integer> waitForInteger = ContextAggregator.ContextWait.create();

ContextAggregator.waitFor(waitForString, waitForInteger)
        .onReady(() -> {
            //当两个等待都被解决时将被调用。
        });

waitForString.complete("some string");
waitForInteger.complete(5);

因此,你可以为服务器调用创建一个等待上下文,同时将 UI 的初始化移动到 onReady 方法中。

英文:

For doing those server calls you can also use domino-rest which already have an implementation for android domino-rest-android and to make several calls and wait for them to finish you could try using domino-aggregator

with domino-aggregator you can do something like the following

ContextAggregator.ContextWait&lt;String&gt; waitForString = ContextAggregator.ContextWait.create();
ContextAggregator.ContextWait&lt;Integer&gt; waitForInteger = ContextAggregator.ContextWait.create();

ContextAggregator.waitFor(waitForString, waitForInteger)
        .onReady(() -&gt; {
            //will be called when both waits are resolved.
        });

waitForString.complete(&quot;some string&quot;);
waitForInteger.complete(5);

so simply you could make a waiting context for the server call, meanwhile move the initialization of the UI into the onReady method.

答案3

得分: 1

两个答案都指出了解决你的问题的方法。它们还展示了另外两种 - 我认为是现代的 - 从服务器获取数据的方式。

你在以下代码中遇到的问题是:

Cursor cursor = databaseHelper.retrieveData(&quot;select * from &#39;0-1&#39;&quot;);
	label.setText(&quot;Column-count: &quot;+cursor.getColumnCount());

那个 'retrieveData' 调用了服务器,但不会等待服务器返回。这是异步调用的本质。

将 'label.setText("Column-count: "+cursor.getColumnCount());' 移动到 'onSuccess' 方法中,它就会起作用。

Cursor(String sql) {
    greetingService = GWT.create(GreetingService.class);
    columns = new ArrayList&lt;&gt;();
    rows = new ArrayList&lt;&gt;();
    currentPosition = -1;
    
    greetingService.greetServer(sql, new AsyncCallback&lt;List&lt;List&lt;String&gt;&gt;&gt;() {
        @Override
        public void onFailure(Throwable caught) {}
        
        @Override
        public void onSuccess(List&lt;List&lt;String&gt;&gt; result) {
            if (!result.isEmpty()) {
                columns = result.get(0);
                if (result.size() &gt; 1) {
                    rows.addAll(result.subList(1, result.size()));
                }
            }
            label.setText(&quot;Column-count: &quot;+cursor.getColumnCount());
        }
    });
}
英文:

Both answers before point out the solution to your problem. And they show two more - and I think modern - ways to get data from the server.

Your problem with the following code is:

Cursor cursor = databaseHelper.retrieveData(&quot;select * from &#39;0-1&#39;&quot;);
	label.setText(&quot;Column-count: &quot;+cursor.getColumnCount());

that 'retrieveData' calls the server but does not wait until the server returns. That's the nature of asynchronous calls.

Move 'label.setText("Column-count: "+cursor.getColumnCount());' into the 'onSuccess'-method and it will work.

Cursor(String sql) {
    greetingService = GWT.create(GreetingService.class);
    columns = new ArrayList&lt;&gt;();
    rows = new ArrayList&lt;&gt;();
    currentPosition = -1;
    
    greetingService.greetServer(sql, new AsyncCallback&lt;List&lt;List&lt;String&gt;&gt;&gt;() {
        @Override
        public void onFailure(Throwable caught) {}
        
        @Override
        public void onSuccess(List&lt;List&lt;String&gt;&gt; result) {
            if (!result.isEmpty()) {
                columns = result.get(0);
                if (result.size() &gt; 1) {
                    rows.addAll(result.subList(1, result.size()));
                }
            }
            label.setText(&quot;Column-count: &quot;+cursor.getColumnCount());
        }
    });
}

huangapple
  • 本文由 发表于 2020年9月17日 16:10:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/63933892.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定