display image in GWT - image

I have created a widget to display the slideshow.In firefox,everything is fine but in chrome nothing happens. After I refresh with many times, the slideshow is displayed. I don't know Why. Can you give me some ideas? Tks
This is my GWT client:
public SlideClient() {
super();
setStyleName("flexslider");
setHeight("100%");
setWidth("100%");
}
#Override
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
this.client = client;
this.paintableId = uidl.getId();
listImage = Arrays.asList(uidl.getStringArrayAttribute("listImage"));
listUrl = Arrays.asList(uidl.getStringArrayAttribute("listUrl"));
loadImage();
checkImagesLoadedTimer.run();
}
public void display() {
m.setStyleName("slides");
m.setHeight("100%");
m.setWidth("100%");
add(m);
}
public native void slideshow() /*-{
$wnd.$('.flexslider').flexslider({slideshowSpeed: 2000});
}-*/;
public native String getURL(String url)/*-{
return $wnd.open(url,
'target=_blank')
}-*/;
private Timer checkImagesLoadedTimer = new Timer() {
#Override
public void run() {
if (loadedImageElements.size() == toLoad) {
display();
} else {
add(new Label("đang load "+loadedImageElements.size()));
checkImagesLoadedTimer.schedule(2000);
}
}
};
private void loadImage() {
for (String tmp : listImage) {
AbsolutePanel panel = new AbsolutePanel();
final Image ima = new Image(tmp);
add(new Label("before put"));
ima.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event) {
loadedImageElements.put(toLoad+"", ima);
slideshow();
add(new Label("đang put "+loadedImageElements.size()));
}
});
add(new Label("after put"));
panel.add(ima);
m.add(panel);
if (toLoad != 0) {
panel.setVisible(false);
}
toLoad++;
}
}
}

Did you implement an Image Loader to prepare your images before they are displayed? A clean solution would be to add the image elements to your page root as an invisible istance, wait for them to load and then use them elsewhere.
You should check out the tutorials about ImageBundling as well: ImageResource
Here's a little extract from one of my image loader classes as you requested, altough there are different ways to realize that:
private HashMap<String,ImageElement> loadedImageElements = new HashMap<String,ImageElement>();
private int toLoad = 0;
private void loadImage(final String name, String url){
final Image tempImage = new Image(url);
RootPanel.get().add(tempImage);
++toLoad;
tempImage.addLoadHandler(new LoadHandler(){
public void onLoad(LoadEvent event) {
loadedImageElements.put(name,ImageElement.as(tempImage.getElement()));
tempImage.setVisible(false);
}
});
}
The image url is retrieved via a ClientBundle-Interface pointing towards the real positions of the images.
I also implemented a timer running in the background to check if all the images have been loaded:
private Timer checkImagesLoadedTimer = new Timer(){
public void run() {
System.out.println("Loaded " + loadedImageElements.size() + "/" + toLoad + " Images.");
if(loadedImageElements.size() == toLoad){
buildWidget();
}else{
checkImagesLoadedTimer.schedule(50);
}
}
};
After everythign is ready, the original widget/page is created.
But as I said there are many ways to implement image loaders. Try out different implementations and select one that suits your needs best.

Related

Toast is shown every time when device is rotate

In my Android app I use AAC.
Here my activity:
public class AddTraderActivity extends AppCompatActivity {
AddTraderViewModel addTraderViewModel;
private static final String TAG = AddTraderActivity.class.getName();
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AddTraderActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.add_trader_activity);
binding.setHandler(this);
init();
}
private void init() {
ViewModelProvider viewViewModelProvider = ViewModelProviders.of(this);
addTraderViewModel = viewViewModelProvider.get(AddTraderViewModel.class);
Observer<String> () {
#Override
public void onChanged (String message){
Debug.d(TAG, "onChanged: message = " + message);
Toast.makeText(AddTraderActivity.this, message, Toast.LENGTH_LONG).show();
}
});
}
public void onClickStart() {
EditText baseEditText = findViewById(R.id.baseEditText);
EditText quoteEditText = findViewById(R.id.quoteEditText);
addTraderViewModel.doClickStart(baseEditText.getText().toString(), quoteEditText.getText().toString());
}
}
Here my ViewModel:
public class AddTraderViewModel extends AndroidViewModel {
private MutableLiveData<String> messageLiveData = new MutableLiveData<>();
private static final String TAG = AddTraderViewModel.class.getName();
public AddTraderViewModel(#NonNull Application application) {
super(application);
}
public void doClickStart(String base, String quote) {
Debug.d(TAG, "doClickStart: ");
if (base.trim().isEmpty() || quote.trim().isEmpty()) {
String message = getApplication().getApplicationContext().getString(R.string.please_input_all_fields);
messageLiveData.setValue(message);
return;
}
}
public LiveData<String> getMessageLiveData() {
return messageLiveData;
}
}
So when I click on button on Activity call method onClickStart()
If any fields is empty the show toast. In the activity call method:
onChanged (String message)
Nice. It's work fine.
But the problem is, when I rotate the device in the activity method onChanged(String message) is called AGAIN and as result show toast. This happened on every rotation.
Why?
This is the expected behaviour. If you want to avoid this you must set message = "" and keep an empty check before showing the toast.
A better way to use it is something like Event Wrapper or SingleLiveEvent
Highly recommend you to read this article. This explains why you are facing this and what are your options in detail.

Best approach to use DiffUtil with LIveData + Room Database?

I am using Room Database with LiveData , but my Local Database is updating too fast as per our requirement and at the same time i have to reload my recycler view .instead of calling notifyDataSetChanged() to adapter , i am trying to use DiffUtil , but is crashing or not reloading properly , this is uncertain .
i am following this tutorial :
Tutorials Link here
MyAdapter :
public class SwitchGridAdapter extends RecyclerView.Adapter<SwitchGridAdapter.ViewHolder> {
private List<Object> allItemsList;
private LayoutInflater mInflater;
private OnItemClickListener mClickListener;
private Context context;
private Queue<List<Object>> pendingUpdates =
new ArrayDeque<>();
// data is passed into the constructor
public SwitchGridAdapter(Context context,List<Appliance> applianceList,List<ZmoteRemote> zmoteRemoteList) {
this.mInflater = LayoutInflater.from(context);
this.context = context;
allItemsList = new ArrayList<>();
if (applianceList!=null) allItemsList.addAll(applianceList);
if (zmoteRemoteList!=null)allItemsList.addAll(zmoteRemoteList);
}
// inflates the cell layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R .layout.switch_grid_item, parent, false);
return new ViewHolder(view);
}
// binds the data to the textview in each cell
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// Doing some update with UI Elements
}
// total number of cells
#Override
public int getItemCount() {
return allItemsList.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,View.OnLongClickListener {
TextView myTextView;
ImageView imgSwitch;
ViewHolder(View itemView) {
super(itemView);
myTextView = (TextView) itemView.findViewById(R.id.txtSwitchName);
imgSwitch = (ImageView) itemView.findViewById(R.id.imgSwitchStatus);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
#Override
public void onClick(View view) {
// handling click
}
#Override
public boolean onLongClick(View view) {
return true;
}
// convenience method for getting data at click position
Object getItem(int id) {
return allItemsList.get(id);
}
// allows clicks events to be caught
public void setClickListener(OnItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface OnItemClickListener {
void onItemClick(View view, int position);
void onItemLongPressListner(View view, int position);
}
// ✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
// From This Line Reloading with Diff Util is Done .
//✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
public void setApplianceList( List<Appliance> applianceList,List<ZmoteRemote> zmoteRemoteList)
{
if (allItemsList == null)
allItemsList = new ArrayList<>();
List<Object> newAppliances = new ArrayList<>();
if (applianceList!=null) newAppliances.addAll(applianceList);
updateItems(newAppliances);
}
// when new data becomes available
public void updateItems(final List<Object> newItems) {
pendingUpdates.add(newItems);
if (pendingUpdates.size() > 1) {
return;
}
updateItemsInternal(newItems);
}
// This method does the heavy lifting of
// pushing the work to the background thread
void updateItemsInternal(final List<Object> newItems) {
final List<Object> oldItems = new ArrayList<>(this.allItemsList);
final Handler handler = new Handler();
new Thread(new Runnable() {
#Override
public void run() {
final DiffUtil.DiffResult diffResult =
DiffUtil.calculateDiff(new DiffUtilHelper(oldItems, newItems));
handler.post(new Runnable() {
#Override
public void run() {
applyDiffResult(newItems, diffResult);
}
});
}
}).start();
}
// This method is called when the background work is done
protected void applyDiffResult(List<Object> newItems,
DiffUtil.DiffResult diffResult) {
dispatchUpdates(newItems, diffResult);
}
// This method does the work of actually updating
// the backing data and notifying the adapter
protected void dispatchUpdates(List<Object> newItems,
DiffUtil.DiffResult diffResult) {
// ❌❌❌❌❌❌ Next Line is Crashing the app ❌❌❌❌❌
pendingUpdates.remove();
dispatchUpdates(newItems, diffResult);
if (pendingUpdates.size() > 0) {
updateItemsInternal(pendingUpdates.peek());
}
}
}
Observing LiveData
public void setUpAppliancesListLiveData()
{
if (applianceObserver!=null)
{
applianceObserver = null;
}
Log.e("Appliance Fetch","RoomName:"+this.roomName);
applianceObserver = new Observer<List<Appliance>>() {
#Override
public void onChanged(#Nullable List<Appliance> applianceEntities) {
// Log.e("Appliance Result","Appliance List \n\n:"+applianceEntities.toString());
new Thread(new Runnable() {
#Override
public void run() {
List<Appliance> applianceListTemp = applianceEntities;
zmoteRemoteList = new ArrayList<>(); //appDelegate.getDatabase().zmoteRemoteDao().getRemoteList(roomName);
// Sort according to name
Collections.sort(applianceListTemp, new Comparator<Appliance>() {
#Override
public int compare(Appliance item, Appliance t1) {
String s1 = item.getSwitchName();
String s2 = t1.getSwitchName();
return s1.compareToIgnoreCase(s2);
}
});
if(getActivity()!=null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
applianceList = applianceListTemp;
mRecyclerView.getRecycledViewPool().clear();
adapter.setApplianceList(applianceList,zmoteRemoteList);
}
});
}
}
}).start();
}
};
appDelegate.getDatabase().applianceDao().getApplinaceListByRoomName(this.roomName).observe(this, applianceObserver);
}

Http Range request Streaming video from url into exoplayer

I tried a lot to find the solution to my problem. but I can't make it correct. I want to show and download video from URL. Url will be like
https://imgur.com/a/dW7kLCv
As far my research API in python language and it used partial content with range request in the header. I don't know how to use that API and load video into video view/exoplayer.I tried below way and I got this issue.
" com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 500"
Anyone pls give me a way to use that api to show and download video
mPlayerView = findViewById(R.id.videoView);
mPlayerView.requestFocus();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
mPlayerView.setPlayer(player);
player.setPlayWhenReady(shouldAutoPlay);
MediaSource mediaSource = new ExtractorMediaSource.Factory(mediaDataSourceFactory)
.createMediaSource(Uri.parse(videoPath));
boolean haveStartPosition = currentWindow != C.INDEX_UNSET;
if (haveStartPosition) {
player.seekTo(currentWindow, playbackPosition);
}
player.prepare(mediaSource, !haveStartPosition, false);
player.addListener(new ExoPlayer.EventListener() {
#Override
public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == ExoPlayer.STATE_BUFFERING) {
progressBar.setVisibility(View.VISIBLE);
} else {
progressBar.setVisibility(View.INVISIBLE);
}
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
});

How can I show Video List properly?

I've been searching everywhere for the solution, but it has come to a dead end.
Please help!
I record and save the video as the follow:
File DirectoryFile = new File(VideoPath);
recorder.setOutputFile(DirectoryFile.getAbsolutePath());
I load all the videos and set the ListView adapter from the userPath as follow:
private File[] getNewImageFilesWithFilters() {
File directory = new File(UserSavedDirectoryPATH);
return directory.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.toLowerCase(Locale.getDefault()).endsWith(".mp4")
|| name.toLowerCase(Locale.getDefault()).endsWith(".mkv");
}
});
}
public void LoadListView() {
for (File file : listFile){
mVideoListViewObject = new VideoListViewObject();
mVideoListViewObject.setName(file.getName());
mVideoListViewObject.setVideoUrl(file.getAbsolutePath());
VideoListViewObject_List.add(mVideoListViewObject);
}
mVideoListViewAdapter = new VideoListAdapter(this, VideoListViewObject_List);
mListView.setAdapter(mVideoListViewAdapter);
}
The ListView Adapter:
public class VideoListAdapter extends BaseAdapter {
private List<VideoListViewObject> VideoObjectList;
private Context mContext;
public VideoListAdapter(Context context, List<VideoListViewObject> newList){
this.mContext = context;
this.VideoObjectList = newList;
}
#Override
public int getCount() {
return VideoObjectList.size();
}
#Override
public VideoListViewObject getItem(int position) {
return VideoObjectList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.listview_layout, parent, false);
viewHolder.imageView = (ImageView)convertView.findViewById(R.id.ListViewImage);
viewHolder.layout = (RelativeLayout)convertView.findViewById(R.id.ListViewLayout);
convertView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder)convertView.getTag();
}
Bitmap bmThumbnail = ThumbnailUtils.createVideoThumbnail(VideoObjectList.get(position).getVideoUrl(),Thumbnails.MICRO_KIND);
viewHolder.imageView.setImageBitmap(bmThumbnail);
The problem is the list is slow to load, especially when there are a lot of videos.
This causes my VideoaAtivity to start very slow.
I love Piscasso and Universal Image Loader, but they only support images.
Does anyone know a better solution or a library that would help with the performance?
Thank you very much.
I just modified my own application to do similar logic to pre-create the thumbnails which made the list scroll very fast at the start, Add the thumbnail bitmap to the videoListViewObject and create the thumbnail
when loading the video list. this way you do not have to create it every time getView is called in your adapter.
public class VideoListViewObject{
private Bitmap bitmap = null;
............................
public void setBitmap(Bitmap bitmap)
{
this.bitmap = bitmap;
}
public Bitmap getBitmap()
{
return this.bitmap;
}
}
public void LoadListView() {
for (File file : listFile){
mVideoListViewObject = new VideoListViewObject();
mVideoListViewObject.setName(file.getName());
mVideoListViewObject.setVideoUrl(file.getAbsolutePath());
Bitmap bmThumbnail = ThumbnailUtils.createVideoThumbnail(VideoObjectList.get(position).getVideoUrl(),Thumbnails.MICRO_KIND);
mVideoListViewObject.setBitmap(bmThumbnail);
VideoListViewObject_List.add(mVideoListViewObject);
}
mVideoListViewAdapter = new VideoListAdapter(this, VideoListViewObject_List);
mListView.setAdapter(mVideoListViewAdapter);
}
then change your BaseAdapter code to only create the thumbnail if it is null,
public class VideoListAdapter extends BaseAdapter {
private List<VideoListViewObject> VideoObjectList;
private Context mContext;
public VideoListAdapter(Context context, List<VideoListViewObject> newList){
this.mContext = context;
this.VideoObjectList = newList;
}
#Override
public int getCount() {
return VideoObjectList.size();
}
#Override
public VideoListViewObject getItem(int position) {
return VideoObjectList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.listview_layout, parent, false);
viewHolder.imageView = (ImageView)convertView.findViewById(R.id.ListViewImage);
viewHolder.layout = (RelativeLayout)convertView.findViewById(R.id.ListViewLayout);
convertView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder)convertView.getTag();
}
VideoListViewObject mVideoListViewObject = getItem(position);
Bitmap bmThumbnail = mVideoListViewObject.getBitmap();
if(bmThumbnail==null)
{
bmThumbnail = ThumbnailUtils.createVideoThumbnail(VideoObjectList.get(position).getVideoUrl(),Thumbnails.MICRO_KIND);
}
viewHolder.imageView.setImageBitmap(bmThumbnail);

GWT application crashes in latest Firefox versions 21 and above

We have a GWT application which crashes in Firefox versions 21 and above, including in the latest version 23.0.1. In earlier versions of Firefox and IE 9, it works fine. This is in deployed mode and not because of the GWT plugin. The situation it crashes is when there are huge number of RPC calls, may be around 300 to 400.
As the application in which it happens is fairly complex, I tried to simulate this issue with a simple prototype. I observed that my prototype crashes when the number of RPC calls reach 100000. But this scenario is very unlikely in my application where RPC calls are around 300-400 as observed using Firebug.
I am trying to find out what else I am missing in my prototype so that it also crashes with 300-400 RPC calls.
GWT version - 2.4
GXT version - 2.2.5
package com.ganesh.check.firefox.client;
public class FirefoxCrash implements EntryPoint {
private static final String SERVER_ERROR = "An error occurred while "
+ "attempting to contact the server. Please check your network "
+ "connection and try again.";
private final GreetingServiceAsync greetingService = GWT
.create(GreetingService.class);
public native static void consoleLog(String text)/*-{
$wnd.console.log(text);
}-*/;
public void onModuleLoad() {
final Button sendButton = new Button("Send");
final TextBox nameField = new TextBox();
nameField.setText("GWT User");
final Label errorLabel = new Label();
final Label countLabel = new Label();
// We can add style names to widgets
sendButton.addStyleName("sendButton");
// Add the nameField and sendButton to the RootPanel
// Use RootPanel.get() to get the entire body element
RootPanel.get("nameFieldContainer").add(nameField);
RootPanel.get("sendButtonContainer").add(sendButton);
RootPanel.get("errorLabelContainer").add(errorLabel);
RootPanel.get("count").add(countLabel);
// Focus the cursor on the name field when the app loads
nameField.setFocus(true);
nameField.selectAll();
// Create the popup dialog box
final DialogBox dialogBox = new DialogBox();
dialogBox.setText("Remote Procedure Call");
dialogBox.setAnimationEnabled(true);
final Button closeButton = new Button("Close");
// We can set the id of a widget by accessing its Element
closeButton.getElement().setId("closeButton");
final Label textToServerLabel = new Label();
final HTML serverResponseLabel = new HTML();
VerticalPanel dialogVPanel = new VerticalPanel();
dialogVPanel.addStyleName("dialogVPanel");
dialogVPanel.add(new HTML("<b>Sending name to the server:</b>"));
dialogVPanel.add(textToServerLabel);
dialogVPanel.add(new HTML("<br><b>Server replies:</b>"));
dialogVPanel.add(serverResponseLabel);
dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
dialogVPanel.add(closeButton);
dialogBox.setWidget(dialogVPanel);
// Add a handler to close the DialogBox
closeButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
dialogBox.hide();
sendButton.setEnabled(true);
sendButton.setFocus(true);
}
});
class MyHandler implements ClickHandler, KeyUpHandler {
private int resultCount = 0;
/**
* Fired when the user clicks on the sendButton.
*/
public void onClick(ClickEvent event) {
sendNameToServer();
}
public void onKeyUp(KeyUpEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
sendNameToServer();
}
}
private void sendNameToServer() {
// First, we validate the input.
errorLabel.setText("");
String textToServer = nameField.getText();
// Then, we send the input to the server.
textToServerLabel.setText(textToServer);
serverResponseLabel.setText("");
final int loopCount = Integer.parseInt(textToServer);
resultCount=0;
for (int i = 0; i < loopCount; i++) {
greetingService.getResult(textToServer,
new AsyncCallback<ResultBean>() {
public void onFailure(Throwable caught) {
consoleLog(caught.getMessage());
}
public void onSuccess(ResultBean result) {
//countLabel.setText(++resultCount + "");
resultCount++;
if(resultCount==loopCount){
countLabel.setText(resultCount + "");
}
consoleLog("Result returned for "+resultCount);
}
});
}
}
}
// Add a handler to send the name to the server
MyHandler handler = new MyHandler();
sendButton.addClickHandler(handler);
nameField.addKeyUpHandler(handler);
}
}
public class GreetingServiceImpl extends RemoteServiceServlet implements
GreetingService {
public ResultBean getResult(String name) {
ResultBean result = new ResultBean();
Random random = new Random();
int suffix = random.nextInt();
result.setName("Name "+suffix);
result.setAddress("Address "+suffix);
result.setZipCode(suffix);
result.setDoorNumber("Door "+suffix);
return result;
}
public class ResultBean implements Serializable {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getZipCode() {
return zipCode;
}
public void setZipCode(int zipCode) {
this.zipCode = zipCode;
}
public String getDoorNumber() {
return doorNumber;
}
public void setDoorNumber(String doorNumber) {
this.doorNumber = doorNumber;
}
private String name;
private String address;
private int zipCode;
private String doorNumber;
}

Resources