Hello i have got function like that:
#Override
public boolean checkExist(String name) {
final boolean check[] = new boolean[] { false };
getAllRecordFromServer(new SearchCallback() {
#Override
public void onSearchResult(Map<String, Item> itemsMap) {
//do some action set true when map key equals name
check[0] = true;
}
#Override
public void onSearchError(XMLPacket error) {
// TODO Auto-generated method stub
}
});
return check[0];
}
I`am looking for solution and found some article but i do not know how to do it in gwt :/
This code do not working properly ... as you know this is asynchronous callback.
How can i fix this problem i must return value after callback ends.
It is not possible to return a value from async call in a method as you have done. That is the basic nature of "Asynchronous" call. You never know when it will return ( network/server delay) and hence your code execution does not wait!!!!!
Do not return a boolean from your method. Instead make your method take a callback.
interface MyCallback {
execute(boolean successfl);
}
public void checkExist(String name, MyCallback callback) {
getAllRecordFromServer(new SearchCallback() {
#Override
public void onSearchResult(Map<String, Item> itemsMap) {
//do some action set true when map key equals name
callback.execute(true);
}
#Override
public void onSearchError(XMLPacket error) {
}
});
}
Maybe a cleaner solution might be to use events and an eventbus (which could be private to your class or maybe shared by everyone so that other components can react to that) when you get your result or not. Then listen for these events and treat them accordingly.
getAllRecordFromServer(new SearchCallback() {
#Override
public void onSearchResult() {
eventBus.fireEvent(new FoundEvent());
}
#Override
public void onSearchError() {
eventBus.fireEvent(new NotFoundEvent());
}
});
This code is not working properly ...
The reason is that Your code is in synchronous model and you are making Asynchronous calls.
I am assuming that you are doing something after you got some result in onSearchResult.
So,stop executing your code until you got the response from server, Why because you dont know that the callmay fail sometime.
If you really want to use the value globally ,then
public boolean returnVal=false;
public void checkExist(String name, MyCallback callback) {
getAllRecordFromServer(new SearchCallback() {
#Override
public void onSearchResult(Map<String, Item> itemsMap) {
returnVal=true;
proceedFurther(itemsMap) //your next lines of code in this method.
}
#Override
public void onSearchError(XMLPacket error) {
stopProceedFurther(); //show some error message to user.
}
});
Related
Code
new Retrofit.Builder().baseUrl(Constants.BASE_URL_FILES).addCallAdapterFactory(RxJava3CallAdapterFactory.create()).addConverterFactory(GsonConverterFactory.create()).build().create(RetrofitInterface.class).getCountries().observeOn(AndroidSchedulers.mainThread()).subscribe(new SingleObserver<List<CountryModel>>() {
#Override
public void onSubscribe(#io.reactivex.rxjava3.annotations.NonNull Disposable d) {
MainActivity.activityMainBinding.activityMainLinearProgressIndicatorLoading.setVisibility(View.VISIBLE);
}
#Override
public void onSuccess(#io.reactivex.rxjava3.annotations.NonNull List<CountryModel> countryModels) {
fragmentCountriesBinding.fragmentCountriesRecyclerViewCountries.setAdapter(new CountriesAdapter(requireContext(), countryModels));
MainActivity.activityMainBinding.activityMainLinearProgressIndicatorLoading.setVisibility(View.GONE);
}
#Override
public void onError(#io.reactivex.rxjava3.annotations.NonNull Throwable e) {
MainActivity.activityMainBinding.activityMainLinearProgressIndicatorLoading.setVisibility(View.GONE);
if (!MainActivity.isNetworkConnected(requireContext()))
Snackbar.make(MainActivity.activityMainBinding.getRoot(), R.string.no_internet, BaseTransientBottomBar.LENGTH_INDEFINITE).setMaxInlineActionWidth(1).setAction(R.string.retry, view ->
{
}).show();
else
Snackbar.make(MainActivity.activityMainBinding.getRoot(), R.string.something_went_wrong, BaseTransientBottomBar.LENGTH_INDEFINITE).setMaxInlineActionWidth(1).show();
}
});
RetrofitInterface
public interface RetrofitInterface {
#GET("GetCountries.php")
Single<List<CountryModel>> getCountries();
}
CountryModel
public class CountryModel {
private int countryId;
private String countryName, countryIcon;
public int getCountryId() {
return countryId;
}
public String getCountryName() {
return countryName;
}
public String getCountryIcon() {
return countryIcon;
}
}
As you can see inside the onError method, I want when the user clicks on the retry button must retry the call with the server again.
I read the articles talking about retryWhen method and tried to understand this image, but I can't understand it. And I don't know how to use it with my scenario.
My problem is like this question exactly.
My solution is simple and just a temporary/hack rather than spending couple of days using retryWhen().
In the code below, I encapsulate your request call to a function.
If there is a network error, just do a recursive call with the function until it will be successful.
private void sendRequest(){
new Retrofit.Builder().baseUrl(Constants.BASE_URL_FILES).addCallAdapterFactory(RxJava3CallAdapterFactory.create()).addConverterFactory(GsonConverterFactory.create()).build().create(RetrofitInterface.class).getCountries().observeOn(AndroidSchedulers.mainThread()).subscribe(new SingleObserver<List<CountryModel>>() {
#Override
public void onSubscribe(#io.reactivex.rxjava3.annotations.NonNull Disposable d) {
MainActivity.activityMainBinding.activityMainLinearProgressIndicatorLoading.setVisibility(View.VISIBLE);
}
#Override
public void onSuccess(#io.reactivex.rxjava3.annotations.NonNull List<CountryModel> countryModels) {
fragmentCountriesBinding.fragmentCountriesRecyclerViewCountries.setAdapter(new CountriesAdapter(requireContext(), countryModels));
MainActivity.activityMainBinding.activityMainLinearProgressIndicatorLoading.setVisibility(View.GONE);
}
#Override
public void onError(#io.reactivex.rxjava3.annotations.NonNull Throwable e) {
MainActivity.activityMainBinding.activityMainLinearProgressIndicatorLoading.setVisibility(View.GONE);
if (!MainActivity.isNetworkConnected(requireContext()))
Snackbar.make(MainActivity.activityMainBinding.getRoot(), R.string.no_internet, BaseTransientBottomBar.LENGTH_INDEFINITE).setMaxInlineActionWidth(1).setAction(R.string.retry, view ->
{
}).show();
// IF NO NETWORK AVAILABLE just do recursive call of the method
sendRequest();
else
Snackbar.make(MainActivity.activityMainBinding.getRoot(), R.string.something_went_wrong, BaseTransientBottomBar.LENGTH_INDEFINITE).setMaxInlineActionWidth(1).show();
}
});
}
I didn’t reach a solution, so I decided to use retryUntil instead of retryWhen.
I've created an Asynctask in an activity and now i want to return the variable "realimage" to that Asynctask but i cant seem to access it...
public class PhotoUtils
{
public static Photo getImage(String id)
{
unsplash.getPhoto(id, new Unsplash.OnPhotoLoadedListener()
{
#Override
public void onComplete(Photo photo)
{
Photo realImage=photo;
}
#Override
public void onError(String error)
{
}
});
return realImage; //This line shows error that cannot resolve symbol
realImage
}
}
This is my Async Task which is in the other activity
public class ImageTask extends AsyncTask<Photo,Void,Photo>
{
#Override
protected Photo doInBackground(Photo... photos)
{
Intent intent=getIntent();
Bundle bd=intent.getExtras();
String getId = (String) bd.get("id");
Photo finalPhoto=PhotoUtils.getImage(getId);
return finalPhoto;
}
#Override
protected void onPostExecute(Photo finalPhoto) {
tv1.setText(finalPhoto.getId());
super.onPostExecute(finalPhoto);
}
}
First, looks like you don't even need an Asynctask. Look at the example code
Secondly, you can't return it like that.
OnPhotoLoadedListener is an asynchronous callback.
Just use the image as normal within onComplete.
If you needed to pass back the image to the calling method, extract the callback to a parameter.
// this is void now
public static void getImage(String id, Unsplash.OnPhotoLoadedListener listener) {
unsplash.getPhoto(id, listener);
});
Call this as
PhotoUtils.getImage(id, new Unsplash.OnPhotoLoadedListener() {
// Use image in here
});
Which, if you look closely, all you did was replace normal usage of unsplash.getPhoto with PhotoUtils.getImage, which may be want you want, but you could accomplish a similar approach with a singleton pattern around the unsplash instance variable. That way, you're not rewriting all of Unsplash API calls
I have a really basic FormEditor and FormPage:
public class CustomFieldSetVersionEditor extends FormEditor {
#Override
protected void addPages() {
try {
addPage(new MyFormPage(this), getEditorInput());
} catch (final PartInitException ex) {
ex.printStackTrace();
}
}
#Override
public void doSave(final IProgressMonitor monitor) {}
#Override
public void doSaveAs() {}
#Override
public boolean isSaveAsAllowed() { return false; }
}
class MyFormPage extends FormPage {
public MyFormPage(final FormEditor editor) {
super(editor, "id", "Title");
}
#Override
protected void createFormContent(final IManagedForm managedForm) { }
}
This admittedly complex and exotic use case brings the following exception:
java.lang.StackOverflowError
at org.eclipse.swt.widgets.Widget.getData(Widget.java:525)
at org.eclipse.ui.part.MultiPageEditorPart.getEditor(MultiPageEditorPart.java:599)
at org.eclipse.ui.part.MultiPageEditorPart.getActiveEditor(MultiPageEditorPart.java:523)
at org.eclipse.ui.forms.editor.FormEditor.getActiveEditor(FormEditor.java:430)
at org.eclipse.ui.forms.editor.FormEditor$FormEditorSelectionProvider.getSelection(FormEditor.java:84)
at org.eclipse.ui.forms.editor.FormEditor$FormEditorSelectionProvider.getSelection(FormEditor.java:89)
at org.eclipse.ui.forms.editor.FormEditor$FormEditorSelectionProvider.getSelection(FormEditor.java:89)
at org.eclipse.ui.forms.editor.FormEditor$FormEditorSelectionProvider.getSelection(FormEditor.java:89)
...
However, if I use addPage(IFormPage) instead of addPage(IEditorPart, IEditorInput) it works. There is even a "bug" report for this problem: Bug 283039 (it's no bug, because... there is no reason given).
We don't need to discuss if this is a bug, but what I want to know is: How do I add a FormPage to a FormEditor while still defining the IEditorInput?
The FormPage is being initialized twice, the second time with the same IEditorSite as the main FormEditor. This results in the same selection provider being used for the FormPage as the main editor, this selection provider does not expect this and gets in to a loop.
You can stop the second initialization by overriding the isEditor method of FormPage and return true:
#Override
public boolean isEditor() {
return true;
}
Also note that if you use the addPage(IFormPage) call the page is still initialized with the editor input (as long as isEditor returns false).
I'm trying to select first root node of the CellTree after asynchronous data fetching from server. Here is my code:
public class MyTreeModel implements TreeViewModel{
private MyServiceAsync myService = GWT.create(MyService.class);
public <T> NodeInfo<?> getNodeInfo(T value) {
Cell<MyTO> cell = new AbstractCell<MyTO>() {
#Override
public void render(Context context, MyTO value, SafeHtmlBuilder sb) {
//rendering node...
}
};
return new DefaultNodeInfo<MyTO>(value instanceof MyTO ?
createBranchDataProvider((MyTO)value) : //fetching child nodes
cerateRootDataProvider(), cell); //fetching root nodes
}
#Override
public boolean isLeaf(Object value) {
if (value instanceof MyTO) {
MyTO to = (MyTO)value;
return to.isLeafNode();
}
return false;
}
private AbstractDataProvider<MyTO> cerateRootDataProvider() {
AsyncDataProvider<MyTO> dataProvider = new AsyncDataProvider<MyTO>() {
#Override
protected void onRangeChanged(HasData<MyTO> display) {
AsyncCallback<List<MyTO>> callback = new AsyncCallback<List<MyTO>>() {
#Override
public void onSuccess(List<MyTO> result) {
updateRowCount(result.size(), true);
updateRowData(0, result);
}
#Override
public void onFailure(Throwable caught) {
Window.alert(caught.toString());
}
};
myService.getRootNodes(callback);
}
};
return dataProvider;
}
private AbstractDataProvider<MyTO> createBranchDataProvider(final MyTO value) {
AsyncDataProvider<MyTO> dataProvider = new AsyncDataProvider<MyTO>() {
#Override
protected void onRangeChanged(HasData<MyTO> display) {
AsyncCallback<List<MyTO>> callback = new AsyncCallback<List<MyTO>>() {
#Override
public void onSuccess(List<MyTO> result) {
updateRowCount(result.size(), true);
updateRowData(0, result);
}
#Override
public void onFailure(Throwable caught) {
Window.alert(caught.toString());
}
};
myService.getChildNodes(value.getId(), callback);
}
};
return dataProvider;
}
For data which stored on client side solution looks pretty simple: we could just call something like
tree.getRootTreeNode().setChildOpen(0, true, true);
but if we want to fetch data asynchronously we will catch IndexOutOfBoundsException in case we try the same immediately after creation tree, because data is not obtained yet. How can I know when onSuccess() event will be fired in cerateRootDataProvider()? Or I could use another solution? Please suggest something.
I see two options for calling
tree.getRootTreeNode().setChildOpen(0, true, true);
in a right moment:
Direct dependency on presenter: add a constructor for your MyTreeModel object. Send corresponding presenter as a parameter. Add and call something like presenter.onDataLoadingComplete() at the end of onSuccess method.
Custom event: create your custom event. Fire it at the end of onSuccess method. Subscribe to it in some place where you can call access `tree``object. Call necessary code.
I have an addProductButton, click it and it brings up a DialogBox containing bookNameTextBox, bookCategoryTextBox and addBookButton. Click addBookButton, it inserts the bookNameTextBox and bookCategoryTextBox contents into a database. If successful, it should hide the DialogBox and updateList()
The following code works to accomplish that but I'm not sure if it's proper or if there is a better way to achieve the same results.
Main class
addProductButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
//display addBookDialogBox
AddBookDialog abd = new AddBookDialog();
abd.displayDialog(new Callback() {
#Override
public void onSuccess() {
updateList();
}
public void onFailure() {
}
});
}
});
public void updateList() {
}
AddBookDialog class
public class AddBookDialog extends DialogBox {
private Callback callback;
private static AddBookDialogUiBinder uiBinder = GWT
.create(AddBookDialogUiBinder.class);
interface AddBookDialogUiBinder extends UiBinder<Widget, AddBookDialog> {
}
public AddBookDialog() {
setWidget(uiBinder.createAndBindUi(this));
}
public void displayDialog(Callback callback2) {
callback = callback2;
this.center();
}
#UiHandler("addBookButton")
void onAddBookButtonClick(ClickEvent event) {
//save book to database
Database db = Database.openDatabase("Store", "1.0", "My Store", 5 * 1024 * 1024);
db.transaction(new TransactionCallback() {
public void onTransactionStart(SQLTransaction tx) {
tx.executeSql("INSERT INTO products (bookName, bookCategory) VALUES (?, ?)", new Object[] { bookNameTextBox.getText().toString(), bookCategoryTextBox.getText().toString() });
}
public void onTransactionFailure(SQLError error) {
}
public void onTransactionSuccess() {
callback.onSuccess();
}
});
this.hide();
}
}
Callback interface
public interface Callback {
void onSuccess();
void onFailure();
}
I don't see the use of it here, why don't you just put updateList(); inside the onTransactionStart() method ?
CallBacks are used for Asynchronism, and the TransactionCallback here already does that, so I don't see why you would use another callback inside.
And by the way, if you did need a callback, why don't you use the AsyncCallback provided by gwt?
EDIT :
Then the appropriate way is to make an interface with your updateList() method. Make your main class implement it, and change the parameter type of your displayDialog() method to your interface type instead of CallBack type.