0

Pre-Background: I'm using Firebase for database storage, for those of you who don't know how that works: when an object is stored/deleted/modified in Firebase (whether it be a String, int, etc), Firebase sends out an updated packet of info to the mobile devices that are listening with all of the new information. The thing is that Firebase doesn't send only the new object that was stored, it sends over everything in that node again.

Background: In order to find out if something was added to Firebase, I decided to make two int variables. One called "oldCount" and one called "newCount". They were both set to 0 onCreate(). Everytime Firebase sent a new update packet ("onDataChange") I did the following:

oldCount = currentCount;  
currentCount = list.size();  

"list" is an arraylist that I create from the info that Firebase sends. If currentCount>oldCount then data was added and I can proceed with my code.

Problem: After adding these two lines my memory usage increased, the latency between my device and Firebase increased, and a simple animation I had didn't work, my thread was skipping around ~200 frames. It sounds ridiculous, but after removing those two lines everything works fine, memory OK, no frame skips. I plan on looking for a different way to check if data was added, but I just found this error to be so strange, I was hoping someone could shed some light on what's going on.

Relevant Code:

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

private GoogleMap mMap;

private boolean mapReady = false;
private boolean firstLoad = true;

private int loadCount;

private ArrayList<> list;

private DatabaseReference Reference;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);

    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);

    list = new ArrayList<>();
    loadCount = 0;
    setUpData();

private void setUpData() {
    Query query = openTicketsReference.orderByChild("variableX").equalTo("variableY");
    query.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                listOfInspections = new ArrayList<>();
                for (DataSnapshot ref : dataSnapshot.getChildren()) {
                    //get data and add to arraylist here  
                }
                loadCount++; //see how many times data has been retrieved from server
            }
            setUpMarkers();
    }  

private void setUpMarkers() {
    if(loadCount<2){    
        Log.v("loadCount<2",""+loadCount);
        //do things for first data retrieval    
    }  
    else if (loadcount>1){  
         Log.v("loadCount>1",""+loadCount);
        //do things for subsequent retrievals  
    }  
}    

}

What I'm seeing in these logs at the end is a bit confusing too:

(This is after adding data to firebase)

V/loadCount>1: 33  
V/loadCount>1: 11  
V/loadCount>1: 8  
V/loadCount>1: 34  
V/loadCount>1: 34  
V/loadCount>1: 12  
V/loadCount>1: 9  
V/loadCount>1: 35  
V/loadCount>1: 35  
V/loadCount>1: 13  
V/loadCount>1: 10  
V/loadCount>1: 36  
V/loadCount>1: 36  
V/loadCount>1: 14  
V/loadCount>1: 11  

They should never be decreasing as I never subtract from the variable, only add (after setting it to 0 onCreate()).

Gabe
  • 46
  • 1
  • 8
  • 3
    I was thinking that maybe `list.size()` was triggering some sort of costly API call, but if `list` be a simple `ArrayList`, then this should not be the case. Could you also post the relevant Java code? – Tim Biegeleisen Nov 02 '16 at 05:08
  • Is the list accessed by different threads? – Naveen Dissanayake Nov 02 '16 at 05:22
  • The list isn't directly accessed by different threads, it is checked for a size difference like stated above and if there is a difference it passes the last item in the list to a handler. [This](http://stackoverflow.com/questions/13189054/implement-falling-pin-animation-on-google-maps-android/20241972#20241972) is the handler method I used. – Gabe Nov 02 '16 at 05:40
  • I can add the relevant Java code tomorrow when I have a bit more time. Sorry for not being able to add it right away. – Gabe Nov 02 '16 at 05:40

2 Answers2

1

I assume this is because list points to some virtual structure which actually doesn't directly in the memory of your application.

Therefore either some remote call is involved which needs to get the size of the list at least or maybe even worse it asks for the full list in other (remote) application and serializes/deserializes the full list of items. Due to that and the latency it delays significantly your original application.

You can probably debug what really happens inside or at least check the type of the class to give a hint.

Zbynek Vyskovsky - kvr000
  • 18,186
  • 3
  • 35
  • 43
0

apply this code in your gradle file :-

android {
    dexOptions {
        javaMaxHeapSize "4g"
    }
}

I hope this will help you.

rookieDeveloper
  • 2,459
  • 1
  • 22
  • 44
LoveAndroid
  • 186
  • 1
  • 11