I got a really annoying problem with my realtime graph. It works really pretty with MpAndroidChart library, but I guess I'm running out of memory. Because my realtime lineChart-graph become slower the longer it's running, until it get stuck. I didn't find any solution that works.
This is my linecharts screenshot
This is my code to enter values into charts,
( test01 - test04 are possible solution from other posts, I tried )
private void addEntry(double[][] pts) {
// System.out.println("######### addEntry #########");
if (mLineChartObj != null) {
int anzLineChartObj = mLineChartObj.size();
// System.out.println("######### Anzahl LineChartObj: " + anzLineChartObj);
for (int i = 0; i < anzLineChartObj; i++) {
LineChartObject ob = mLineChartObj.get(i);
LineData data = ob.lineChart.getData();
if (data != null) {
data.addXValue((ob.set).getEntryCount() + "");
data.addEntry(new Entry((float) pts[ob.rootNodePos][0], (ob.set).getEntryCount()), 0);
// data.addEntry(new Entry((float) (Math.random() * 9) + 0.45f, (ob.set).getEntryCount()), 0);
}
// °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
if (data.getXValCount() > 1400) {
System.out.println("X-ValueCount: " + ob.lineChart.getXValCount() + " EntryValueCount: " + ob.set.getEntryCount() + " ###############################");
// Test 01 °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// for (int j = 0; j < 400; j++) {
// data.removeXValue(0);
// ob.set.removeEntry(0);
// }
// Test 02 °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// runOnUiThread(new Runnable() {
// #Override
// public void run() {
// ob.lineChart.clearValues();
// }
// });
// Test 03 °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// for (int j = 400; j > 0; j--) {
// data.removeXValue(j + 999);
// ob.set.removeEntry(j + 999);
// }
// Test 04 °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// data.removeXValue(0);
// ob.set.removeEntry(0);
System.out.println("X-ValueCount: " + ob.lineChart.getXValCount() + " EntryValueCount: " + ob.set.getEntryCount() + " ###############################");
}
// °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// notify chart data have changed
ob.lineChart.notifyDataSetChanged();
// limit number of visible entries
float range = 200f;
// ob.lineChart.setVisibleXRange(0f, range);
ob.lineChart.setVisibleXRangeMaximum(range);
// scroll the last entry
ob.lineChart.moveViewToX(data.getXValCount() - (range + 1f));
}
}
}
If I remove x-values from data or entries from set, several strange things happens. Sometimes the app gets crash, or the line of the charts begin to repeat itself, or sometimes I get more than one line per chart. I'm looking forward of a solution to remove old values from the chart.
EDIT 2: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
The output of my linechart is like the following picture...It moves like a realtime graph, until xValues an amount of reach 1400, now my programm begins to remove entries and my linechart get stuck. After a while, the line begin to dissapear from the left side. At picture 1 it get stuck, at the next three pictures you can see how it dissapears.
I've been stuck with exactly the same problem today as I'm writing an app that visualizes sensor data. I just came up with the following makeshift solution that works for me:
// (following code snippet is from an event listener)
final ArrayList<Float> values = event.getValues();
final LineData data = mChart.getData();
// add data entry
if (mIndex < MAX_PLOT_SIZE) {
maxValue = 0f;
data.addXValue("" + mIndex);
for (int i = 0; i < values.size(); i++) {
final Float val = values.get(i);
final LineDataSet set = data.getDataSetByIndex(i);
set.addEntry(new Entry(val, mIndex));
}
mIndex++;
} else {
// shift values down
for (int i = 0; i < values.size(); i++) {
final LineDataSet set = data.getDataSetByIndex(i);
final List<Entry> yVals = set.getYVals();
final int size = yVals.size();
for (int j = 0; j < size - 1; j++) {
yVals.get(j).setVal(yVals.get(j + 1).getVal());
}
// add new value
final Float val = values.get(i);
yVals.get(size - 1).setVal(val);
}
}
It's admittedly a hack and there should be an easier way to do it, but at least it gets the job done. I guess you could try and adjust the xVal-Strings in the same manner ...
Related
I have to use an algorithm to find a path for a school project. I have a sequence of 12 goals on the map, which must be reached before the end of the path. The map is a 70x70 array. What I already did:
I find all the goals and add in a list
The goals are marked by numbers 10 to 21, and i put on a list 0 to 12. (21 IS THE last goal)
private casa[] acharCasas(){
casa[] casas = new casa[12];
for (int linha = 0; linha < jogo.getMapa().length; linha++) {
for (int coluna = 0; coluna < jogo.getMapa()[0].length; coluna++) {
if(jogo.getMapa()[linha][coluna] >= 10 && jogo.getMapa()[linha][coluna] <= 21){
casas[jogo.getMapa()[linha][coluna]-10] = new casa (linha,coluna);
}
}
}
return casas;
}
I make heuristics total cost + distance from other houses unvisited
casas_visitadas are the number of visited goals, and posL = row, posC = Col. What I wanted to do is calculate the distance from where you are to the next uncompleted objective, + distance from this objective to the next objective... to the final goal.
public double distanciaDasOutrasCasas(){
double somaTotal = 0;
int posL = linha,posC = coluna;
for (int i = casas_visitadas; i < 12; i++) {
somaTotal += Math.sqrt(
Math.pow( (double) (casas[i].linha - posL),2) +
Math.pow( (double) (casas[i].coluna - posC),2)
);
posL = casas[i].linha;
posC = casas[i].coluna;
}
return somaTotal;
}
I check all possible movements
And I add them to the ArrayList. Here are the constructors:
public ArrayList<Direcao> movimentosPossiveis(){
ArrayList<Direcao> movimentos = new ArrayList<>();
if (linha > 0) movimentos.add(Direcao.CIMA); // if isnt the first row add UP
if (coluna > 0) movimentos.add(Direcao.ESQUERDA);//if inst the first col add LEFT
if (linha < jogo.getMapa().length) movimentos.add(Direcao.BAIXO); // last row add down
if (coluna < jogo.getMapa()[linha].length) movimentos.add(Direcao.DIREITA); // add right
return movimentos;
}
public ArrayList<cell> permutaCelula(){
ArrayList<Direcao> movimentos = movimentosPossiveis();
ArrayList<cell> novasCelulas = new ArrayList<>();
for (Iterator<Direcao> iterator = movimentos.iterator(); iterator.hasNext();) {
Direcao D = iterator.next();
switch (D){
case CIMA:
novasCelulas.add(
new cell(this /*father*/, Direcao.CIMA /*direction from father */, custo_total /*total cost*/, linha-1/*row-1*/, coluna/*col*/, casas_visitadas/*goals visiteds*/)
);
break;
case BAIXO:
novasCelulas.add(
new cell(this, Direcao.CIMA, custo_total, linha+1, coluna, casas_visitadas)
);
break;
case ESQUERDA:
novasCelulas.add(
new cell(this, Direcao.CIMA, custo_total, linha, coluna-1, casas_visitadas)
);
break;
case DIREITA:
novasCelulas.add(
new cell(this, Direcao.CIMA, custo_total, linha, coluna+1, casas_visitadas)
);
break;
}
}
return novasCelulas;
}
public double convertePesoDoChao(){
System.out.println(" L " + this.linha + " Coluna "+ coluna);
int chao = jogo.getMapa()[this.linha][this.coluna];
switch (chao) {
case 0:
return 200; //rock field, slowest field
case 1:
return 1;
case 2:
return 3.5;
case 3:
return 5;
case 22:
if(quantidadeDeCavaleirosVivos() != 0) return Double.MAX_VALUE; // cant go to master without find all goals
finalizado = true; // found
caminhoFinal = converteCelulaParaMovimentos(); // converts cells movements
return 0;
default:
casas_visitadas++;
return 0;
}
}
public cell(cell pai, Direcao oPaiMexeuPraQualDirecao, double custo_total, int linha, int coluna, int casas_visitadas) {
this.pai = pai; // father
this.oPaiMexeuPraQualDirecao = oPaiMexeuPraQualDirecao; // direction from father
this.linha = linha; //row
this.coluna = coluna; // col
this.casas_visitadas = casas_visitadas; //goals visited
this.custo_total = custo_total + convertePesoDoChao(); // fathers total cost + field cost
}
public cell(int linha, int coluna) { //starter cell
this.linha = linha;
this.coluna = coluna;
this.custo_total = 0;
this.pai = null;
}
The heuristic
my heuristic is total cost + distancefromgoals
public double heuristica(){
return custo_total *10 + distanciaDasOutrasCasas();
}
Primary loop
if(!finalizado){
this.jogo = jogo;
colunaInicial = jogo.getColuna();
linhaInicial = jogo.getLinha();
casas = acharCasas();
ArrayList<cell> franja = new ArrayList<>();
franja.add(new cell(linhaInicial,colunaInicial));
while(!finalizado){
Collections.sort(franja);
franja.addAll(franja.get(0).permutaCelula());
franja.remove(0);
}
}
The problem
It's taking too long, over three hours total, to find the way... any tips? I checked on the Netbeans profiler, and the problem is sorting the array.
My full code is here
obs: on full code, a game call the action move, and on the first call I need to find the best way, and save it, later I just pop the stack of movements
obs2: sorry my bad english, i used google translator on some parts
Okay, so i dont really know much about writing code, yet. I am working on a project that uses twitter API data. My goal for the project is to use hash tags to represent both good and bad things (for sake of simplicity, lets use #good and #bad).
I want that hashtag data to modify the color of a simple ellipse to a shade of color in between red and green, depending on the number of #good and #bad tweets.
I like to think of it as a +100/-100 spectrum. each #good tweet is +1, each #bad is -1. If it is at -100 tweets, then the ellipse is full red. If it is at +100 tweets, then the ellipse is full green.
I know this is a little complicated, but its for an art project im doing. I followed a tutorial and currently have the twitter data responding on a simple array list of tweets (tutorial # https://www.youtube.com/watch?v=gwS6irtGK-c)
I am using processing, java, twitter4j 3.0.3, and a macbook pro with OSX el capitan 10.11.3
Any help would be greatly appreciated. Even pointing me in the direction on how to code it myself. If you need more information from me, ill respond as quickly as I see it!
ConfigurationBuilder cb = new ConfigurationBuilder();
Twitter twitterInstance;
Query queryForTwitter;
ArrayList tweets;
void setup() {
cb.setOAuthConsumerKey("****");
cb.setOAuthConsumerSecret("****");
cb.setOAuthAccessToken("****");
cb.setOAuthAccessTokenSecret("****");
cb.setUseSSL(true);
twitterInstance = new TwitterFactory( cb.build()
).getInstance();
queryForTwitter = new Query("#good");
size(640,440);
FetchTweets();
} //setup
void draw() {
background(0);
DrawTweets();
} //draw
void DrawTweets() {
for(int i=0; i<tweets.size(); i++) {
Status t = (Status) tweets.get(i);
String user = t.getUser().getName();
String msg = t.getText();
text(user + ": " + msg,
20,15+i*30-mouseY, width-20, 40);
} //for
} //drawTweets
void FetchTweets(){
try {
QueryResult result = twitterInstance.search(
queryForTwitter );
tweets = (ArrayList) result.getTweets();
} catch(TwitterException te) {
println("Couldn't connect: " +te);
} // end of catch TwitterException
}// end of FetchAndDrawTweets()
SECOND VERSION:
ConfigurationBuilder cb = new ConfigurationBuilder();
Twitter twitterInstance;
Query queryForTwitter;
//ArrayList tweets;
void setup() {
cb.setOAuthConsumerKey("****");
cb.setOAuthConsumerSecret("****");
cb.setOAuthAccessToken("****");
cb.setOAuthAccessTokenSecret("****");
cb.setUseSSL(true);
//twitterInstance = new TwitterFactory( cb.build()
// ).getInstance();
//queryForTwitter = new Query("#feelthebern");
size(640,440);
int numGood = 50;
int numBad = 50;
for (int i = 0; i < numGood; i++) {
tweets.add("#good");
}
for (int i = 0; i < numBad; i++) {
tweets.add("#bad");
}
} //setup
ArrayList<String> tweets = new ArrayList<String>();
//create a function that counts the tweets
//that contain a certain hashtag
int countTweets(String hashtag){
int total = 0;
for(String tweet : tweets){
if(tweet.contains(hashtag)){
total++;
}
}
return total;
}
void draw(){
//count the good and bad tweets
int goodTweets = countTweets("#good");
int badTweets = countTweets("#bad");
//calculate color based on tweet counts
float r = badTweets/100.0 * 255;
float g = goodTweets/100.0 * 255;
float b = 0;
background(r, g, b);
}
You have to break your problem down into smaller steps.
Step 1: Create a function that simply returns an ArrayList of tweets.
Step 2: Create a function that takes that ArrayList and a String value, and returns the number of times that String occurs in the tweets in the ArrayList.
This code assumes you have a ArrayList<String> tweets:
int countTweets(String hashtag){
int total = 0;
for(String tweet : tweets){
if(tweet.contains(hashtag)){
total++;
}
}
return total;
}
Step 3: Calculate the color based on the number of tweets containing each word. You said you'll always have 100 tweets, so you can just divide the tweet count by 100, then multiply by 255 to get the color value.
Putting it all together, it looks like this:
ArrayList<String> tweets = new ArrayList<String>();
void setup() {
//you would actually get these from twitter,
//but for testing let's just fill them ourselves
int numGood = 50;
int numBad = 50;
for (int i = 0; i < numGood; i++) {
tweets.add("#good");
}
for (int i = 0; i < numBad; i++) {
tweets.add("#bad");
}
}
//create a function that counts the tweets
//that contain a certain hashtag
int countTweets(String hashtag){
int total = 0;
for(String tweet : tweets){
if(tweet.contains(hashtag)){
total++;
}
}
return total;
}
void draw(){
//count the good and bad tweets
int goodTweets = countTweets("#good");
int badTweets = countTweets("#bad");
//calculate color based on tweet counts
float r = badTweets/100.0 * 255;
float g = goodTweets/100.0 * 255;
float b = 0;
background(r, g, b);
}
I'm currently trying to cluster a great amount of data points into a given amount of clusters and I wanted to try MOA's streaming based k-means StreamKM. A very simple example of what I'm trying to do using random data looks as follows:
StreamKM streamKM = new StreamKM();
streamKM.numClustersOption.setValue(5); // default setting
streamKM.widthOption.setValue(100000); // default setting
streamKM.prepareForUse();
for (int i = 0; i < 150000; i++) {
streamKM.trainOnInstanceImpl(randomInstance(2));
}
Clustering result = streamKM.getClusteringResult();
System.out.println("size = " + result.size());
System.out.println("dimension = " + result.dimension());
The random instances are created as follows:
static DenseInstance randomInstance(int size) {
DenseInstance instance = new DenseInstance(size);
for (int idx = 0; idx < size; idx++) {
instance.setValue(idx, Math.random());
}
return instance;
}
However, when running the given code, no clusters seem to be created:
System.out.println("size = " + result.size()); // size = 0
System.out.println("dimension = " + result.dimension()); // NPE
Is there anything else I need to take care of, or do I have a fundamental misunderstanding of the MOA clustering concepts?
I think prepareForUse() method is not the correct method that initialize the algorithm.
Instead of streamKM.prepareForUse(); , you should use streamKM.resetLearning();.
In short, your code should be like:
StreamKM streamKM = new StreamKM();
streamKM.numClustersOption.setValue(5); // default setting
streamKM.widthOption.setValue(100000); // default setting
streamKM. resetLearning(); // UPDATED CODE LINE !!!
for (int i = 0; i < 150000; i++) {
streamKM.trainOnInstanceImpl(randomInstance(2));
}
Clustering result = streamKM.getClusteringResult();
System.out.println("size = " + result.size());
System.out.println("dimension = " + result.dimension());
I'm trying to display 550 data points with periodic peaks (the flat line is 61). The problem is, that androidplot isn't drawing all the points correctly! From my log:
ECG I values 61,61,62,63,62,61,61,61,61,67,71,68,61,53,61,61,61,61,61,61,61,61,62,63,64,64,64,63,62,61,61,61
I've got the rangeboundaries set to plot.setRangeBoundaries(0,100, BoundaryMode.AUTO);, but as you can see, the peaks never drop to the 53 data point. I can see this lower point sometimes, but it gets smoothed out a fraction of a second later (as you can see in the screenshot).
My line and point formatter is:
LineAndPointFormatter lapf = new LineAndPointFormatter(p.color, null, null, null);
lapf.getLinePaint().setStrokeJoin(Paint.Join.MITER);
lapf.getLinePaint().setStrokeWidth(1);
I've tried with the both Paint.Join.ROUND and Paint.Join.BEVEL and got the same effect. I've also used the debugger to check that 53 is being inserted into the series.
EDIT
After some debugging, it looks like my pulse loop thread is wrong:
while (keepRunning) {
for (PulseXYSeries j : series) {
for (int k = 0; k < j.plotStep; k++) {
int at = (j.position + k) % j.getSize();
if (j.pulsing) {
if (j.pulsePosition == j.pulseValues.size() - 1) {
j.pulsing = false;
j.pulsePosition = 0;
} else {
try {
int pulseVal = j.pulseValues.get(j.pulsePosition);
j.setY(pulseVal,at);
j.pulsePosition += 1;
} catch(IndexOutOfBoundsException e) {
j.pulsePosition = 0;
}
}
} else {
j.setY(j.pulseValues.get(0), at);
long currTime = SystemClock.elapsedRealtime();
if (currTime - j.getLastPulse() >= j.getPulseDelay()) {
j.pulsing = true;
j.setLastPulse(currTime);
}
}
j.remove(((at + j.eraserSize) % j.getSize()));
}
j.position = (j.position + 1) % j.getSize(); // fixed it by changing +1 to + j.plotStep
}
Thread.sleep(delay);
}
My custom series looks like:
private class PulseXYSeries implements XYSeries {
private List<Integer> pulseValues = new ArrayList<Integer>();
private int pulsePerMinute;
public int pulsePosition;
public int position;
private ArrayList<Integer> values;
private String title;
private long lastPulse;
public boolean pulsing = false;
public int eraserSize = 20;
public int plotStep = 3;
}
The code below is taking 27 seconds to load 51 images each image is about 22 KB (timed between the starting and ending alerts I inserted). Is it possible to make it a lot more efficient (I would like to get it to under 3 seconds)?
At first I thought it was the database so I put the alerts in to make sure and found it was this code.
Regards,
Glyn
public void renderYMAwardsTable(List<YouthMemberAwards> ymAwardsList) {
if (!ymAwardsList.isEmpty()) {
flexTableLink.clear();
int linkRow = 0;
int linkCol = 0;
flexTableLeadership.clear();
int leadershipRow = 0;
int leadershipCol = 0;
flexTableBoomerang.clear();
int boomerangRow = 0;
int boomerangCol = 0;
flexTableAchievement.clear();
int achievementRow = 0;
int achievementCol = 0;
flexTableSpecialInterest.clear();
int specialInterestRow = 0;
int specialInterestCol = 0;
totalAwards = 0;
Window.alert("Start populating page.");
for (final YouthMemberAwards ymAwards : ymAwardsList) {
// Display awards and, if applicable, date awarded
if (((ymAwards.getCaAwardedDate() != null)
|| (ymAwards.getAwArchivedDate() == null)
|| (ymAwards.getCaAwardStarted().equals("Y"))
) && (ymAwards.getAwStartedDate().before(ymEndDate))) {
//Display each award in the correct area with:
// the date awarded, if applicable, and
// the date box shaded if the award has been started but not awarded
String imageDataString = ymAwards.getAwAwardPicture();
Image image = new Image(imageDataString);
image.setWidth("75px");
image.setHeight("75px");
image.setStyleName("gwt-Selectable");
final DateBox awardedDate = new DateBox();
awardedDate.setFormat(new DefaultFormat(DateTimeFormat.getFormat("dd/MM/yyyy")));
awardedDate.setValue(ymAwards.getCaAwardedDate());
awardedDate.setWidth("75px");
awardedDate.setFireNullValues(true);
//Check if the Youth Member has started the Award,
//if they have then colour the date box Green.
if (ymAwards.getCaAwardStarted()!= null){
if ((ymAwards.getCaAwardedDate() == null)
&& (ymAwards.getCaAwardStarted().equals("Y"))){
awardedDate.setStyleName("gwt-Green-Background");
}else{
awardedDate.setStyleName("gwt-Label-Login");
}
}else{
awardedDate.setStyleName("gwt-Label-Login");
}
//Tally the number of Awards the Youth Member has been awarded.
if (ymAwards.getCaAwardedDate() != null){
totalAwards = totalAwards + 1;
}
//Display each Award in the appropriate category.
if (ymAwards.getAwAwardType().equals("Link")){
flexTableLink.setWidget(linkRow, linkCol, image);
flexTableLink.setWidget(linkRow + 1, linkCol, awardedDate);
if (linkCol < 10){
linkCol = linkCol + 1;
}else{
linkCol = 0;
linkRow = linkRow + 2;
}
}else{
if (ymAwards.getAwAwardType().equals("Leadership")){
flexTableLeadership.setWidget(leadershipRow, leadershipCol, image);
flexTableLeadership.setWidget(leadershipRow + 1, leadershipCol, awardedDate);
if (leadershipCol < 10){
leadershipCol = leadershipCol + 1;
}else{
leadershipCol = 0;
leadershipRow = leadershipRow + 2;
}
}else{
if (ymAwards.getAwAwardType().equals("Boomerang")){
flexTableBoomerang.setWidget(boomerangRow, boomerangCol, image);
flexTableBoomerang.setWidget(boomerangRow + 1, boomerangCol, awardedDate);
if (boomerangCol < 10){
boomerangCol = boomerangCol + 1;
}else{
boomerangCol = 0;
boomerangRow = boomerangRow + 2;
}
}else{
if (ymAwards.getAwAwardType().equals("Achievement")){
flexTableAchievement.setWidget(achievementRow, achievementCol, image);
flexTableAchievement.setWidget(achievementRow + 1, achievementCol, awardedDate);
if (achievementCol < 10){
achievementCol = achievementCol + 1;
}else{
achievementCol = 0;
achievementRow = achievementRow + 2;
}
}else{
if (ymAwards.getAwAwardType().equals("Special Interest")){
flexTableSpecialInterest.setWidget(specialInterestRow, specialInterestCol, image);
flexTableSpecialInterest.setWidget(specialInterestRow + 1, specialInterestCol, awardedDate);
if (specialInterestCol < 10){
specialInterestCol = specialInterestCol + 1;
}else{
specialInterestCol = 0;
specialInterestRow = specialInterestRow + 2;
}
}else{
//If not found then default to Special Interest.
flexTableSpecialInterest.setWidget(specialInterestRow, specialInterestCol, image);
flexTableSpecialInterest.setWidget(specialInterestRow + 1, specialInterestCol, awardedDate);
if (specialInterestCol < 10){
specialInterestCol = specialInterestCol + 1;
}else{
specialInterestCol = 0;
specialInterestRow = specialInterestRow + 2;
}
}
}
}
}
}
//Add a click handler to the image
image.addClickHandler(new ClickHandler(){
public void onClick(ClickEvent event){
//Store the data from this view for use in subsequent Views (ScoutAwardView).
AsyncCallback<ViewData> callback = new ViewDataStoreHandler<ViewData>();
rpc.setViewData(accountId, accountLevel, youthMemberID, ymAwards.getAwId(), "0", callback);
//If the Award has sub groups then display the Groups and allow one the
//be selected to display the details. Otherwise, display the details.
if (ymAwards.getAwGrouped().equals("Y")) {
//Go to the AwardGroupView
navHandler2.go("AwardGroup");
}else{
//Go to the ScoutAwardView
navHandler2.go("ScoutAward");
}
}
});
//Add change handler for the awarded date.
//Only a Leader or Administrator can update the date
if (accountLevel.equals("Leader") || accountLevel.equals("Administrator")) {
awardedDate.addValueChangeHandler(new ValueChangeHandler<java.util.Date>() {
public void onValueChange(ValueChangeEvent<java.util.Date> event) {
//Check for a null date and handle it for dateBoxArchived and dateBoxPackOut
java.sql.Date sqlDateAwarded = awardedDate.getValue() == null ? null : new java.sql.Date(awardedDate.getValue().getTime());
AsyncCallback<Void> callback = new YMAwardedDateHandler<Void>();
rpc.updateYMAwarded(youthMemberID, ymAwards.getAwId(), sqlDateAwarded, callback);
#SuppressWarnings("unused")
AdjustAwardStock adjustAwardStock = new AdjustAwardStock(sqlDateAwarded, ymAwards.getAwId());
}
});
}
}
}
}
Window.alert("Finish populating page.");
//Hide "Loading please wait" popup.
popup.hide();
//Display the number of Awards earned.
String totalAwardsString = Integer.toString(totalAwards);
textBoxTotalAwards.setText(totalAwardsString);
}
First of all, an image with 75x75 pixels size should not be 22kB. Even a PNG-24 image of this size is about 3kB, let alone GIF. Store your images in the correct sizes and the appropriate file format (use PNG or GIF). For 51 images that means a difference between 1MB and 150kB. This is the first big improvement.
Second, if you use a limited number of images, combine them into a single sprite. This will reduce the number of round-trip server calls from 51 (in your example) to 1. That's another huge improvement.
You don't need to make this sprite manually (unless you want to). You can use GWT's ImageResource ClientBundle. Note that this sprite can be cached, so a browser won't need to load it every time a user visits this page.
The other suggestions (like using switch statements) are good for code readability and maintenance, but they won't give you a significant performance boost because your Java code is compiled into JavaScript, and the compiler is pretty smart.
For combining the images and other JS files, you can always use gzip functionality supported by browser so that all the files can b zipped and send to the browser to unzip. It will lot of network time and transferred data size will b much reduced.