Home > Back-end >  How to get value out of asynchronous listener methods
How to get value out of asynchronous listener methods

Time:08-12

I want to get frame counts which can be obtain on listener's overridden methods.

But if I use try to assign value to outer variable I get error. error: local variables referenced from an inner class must be final or effectively final


public void Test5 (String path, Callback cb){
   // 1. initialised count variable
   int count = 0;
   
   decoder.addRenderListener(
     new WebPDecoder.RenderListener(){
       @Override
       public void onStart(){

         // 2. assigning value to count variable
         count = decoder.getFrameCount();
         Log.d(TAG, count); count is non zero

       }
       @Override
       public void onRender(ByteBuffer byebuffer){}
       
       @Override
       public void onEnd(){
         decoder.stop();
       }
     }
   );
   decoder.start();
   
   // 3. accessing the count variable
   Log.d(TAG,"count : " count);  // still  count is 0
   
   // this won't run as count is 0
   for(int i=0; i < count i  )
       bitmaps.add(decoder.getFrameBitmap(i));
       // and getFrameBitmap(i) is not useful inside above listener overriden methods. This returns bitmap only outside of listener.
 }

I tried SharedPreference and it works but I can't use for reliablity and also app crashes.

I also Tried to use custom class. It does not give error But the value is still zero as it set later. MyData data = new MyData(); used set() and get() for storing and accessing value.

I wonder how sharedPreference gives non zero value but not this custom class

CodePudding user response:

To get around the must be final you may use a

final AtomicInteger count = new AtomicInteger(0);

and then

count.addAndGet(1);

Anyway, line

Log.d(TAG,"count : " count.get());

will always return 0, as long it is before decoder.start(). Probably you want to put into a Handler and run periodically ?.

CodePudding user response:

Well a more effective way to achieve to control this would be using a LiveData object to keep track of the active counts.

Define the count variable as a MutableLiveData<Integer> and update this livedata whenever the onStart method called. This may be much faster than writing to and reading from the shared preferences. See the example snippet for an example implementation.

// Define the live data object within a correct scope in your class
MutableLiveData<Integer> mldCount = new MutableLiveData<>(0);

// In the part where you want to control and avoid the index out of bounds observe the count live data
mldCount.observe(<Pass the lifecycle owner here>, count -> {
    // Check the new count here
});

public void Test5 (String path){
   
   decoder.addRenderListener(
     new WebPDecoder.RenderListener(){
       @Override
       public void onStart(){

         // 2. assigning value to count variable
         int count = decoder.getFrameCount();
         // If this callback is called from a background thread use:
         mldCount.postValue(count);
         
         // If it is called in main thread then use:
         mldCount.setValue(count);
         Log.d(TAG, count); count is non zero

       }
       @Override
       public void onRender(ByteBuffer byebuffer){}
       
       @Override
       public void onEnd(){
         decoder.stop();
       }
     }
   );

   // This will not show the valid actual values
   Log.d(TAG,"count : " mldCount.getValue());  // still  count is 0

   decoder.start();

 }
  • Related