Two async calls in getview(), am I doing this right?
Asked Answered
U

1

1

So, I have a custom GalleryAdapter where I stream images from web with the help of an Async ImageLoading Library via ajax calls (lib name is Aquery).

With the images those I stream from web, I have a corresponding audio track also, with every image and hence that has to be called asynchronously when the image is loaded same time.

i.e.

image file -> http://myserver.com/img1.png

sound track -> http://myserver.com/img1.mp3

  • Point number 1 , I do this whole thing inside my custom ImageAdapter. Shall I call another thread from within my getView method ?

  • What I am doing -> The getView() method gets called 2 times can I control it to get called only once because it shouldn't as the track gets played multiple times based on its call?

This is my Custom Adapter class

private class MainImageAdapter extends ArrayAdapter<String> {

        List<String> pagedImages;
        private Context context;
        
        public MainImageAdapter(Context context,int resid, List<String> objects ) {
            super( context, resid, objects );
            this.context=context;
            this.pagedImages=objects;
        }


           @Override
            public int getCount() {
                // TODO Auto-generated method stub
                return pagedImages.size();
            }
            
            @Override
            public String getItem(int position) {
                // TODO Auto-generated method stub
                return pagedImages.get(position);
            }
            
            @Override
            public long getItemId(int position) {
                // TODO Auto-generated method stub
                return pagedImages.get(position).hashCode();
            }

        @SuppressWarnings("deprecation")
        public View getView(final int position, View convertView, ViewGroup parent) {
            
            View v;
            if ( convertView == null ) {
                v = LayoutInflater.from(context).inflate(R.layout.imagebook, parent, false);
            } else {
                v = convertView;
            } 
            
            System.out.println("getview called with"+position);
            
            final ImageView im=(ImageView) v.findViewById(R.id.pagedimage);
            positionMusic=position;
            
            aq.id(im).image(pagedImages.get(position), true, true, 0, 0, new BitmapAjaxCallback(){
                @Override
                public void callback(String url, ImageView iv, Bitmap bm, AjaxStatus status){
                        iv.setImageBitmap(bm);
                        
                        //This should be called only once somehow
                        mPlayer = MediaPlayer.create(MainActivity.this, Uri.parse(pagedImages.get(position).replace(".png", ".mp3")));
                        mPlayer.start();
                }
            });
            
            
            return v;
        }
    }
Upwards answered 9/5, 2013 at 7:39 Comment(2)
I don't know that library but your code should know somehow if a retrieval task has been started for that row. Regarding a new thread, most likely the library takes care of this and uses a background thread otherwise your app should be slow as hell.Boisleduc
Actual problem that I am facing right now can be solved if I can control the getView to call only once when I swipe the gallery. As I have set the widht and height of my inflated layout as fill_parent, I expect it to run only once, But its not happening.Upwards
A
2

Two async calls in getview(), am I doing this right?

No.

I do this whole thing inside my custom ImageAdapter. Shall I call another thread from within my getView method ?

Aquery is starting another thread to do the download, so you would only duplicate the code they have already. BitmapAjaxCallback.callback is called when that thread finishes doing its job.

The getView() method gets called 2 times can I control it to get called only once because it shouldn't as the track gets played multiple times based on its call?

getView has to be called twice. First call will return View without an image downloaded from the network. Second call is after the image is downloaded and can be attached. Only if you have the image in memory cache already getView will be called once. What you don't want is BitmapAjaxCallback.callback called twice.

Also you are downloading mp3 on main thread after image has finished downloading. They should both be downloaded on separate threads. And simultaneously.

Solution proposition:

As you Adapter is bound to Activity context and downloading of image and mp3 and starting playback should not be bound to that shortliving context, move it to Application context or Service and from Adapter only request things to be done and get image from a cache, which should be put in Application context. Maybe Aquery has some cache you can use.

Adowa answered 9/5, 2013 at 9:0 Comment(7)
Ok. Let's say I have made adapter as a seperate class and do the processing for mp3 download in a different thread, then how does it guarantee that getView would be called only once.Upwards
@pKs "getView has to be called twice." It's a normal adapter behaviour. Basically you have a very messed up application architecture. Making Adapter a separate class doesn't change anything. It will always be bound to Activity context as it is used by AdapterView inside Activity hierarchy.Grogshop
Is there a way to determine what image url I am viewing currently and based on that I would make a call to the server and then stream the audio? I am ready to use a progress dialog until the audio is loaded properly, but I can view the image.Upwards
@pKs As CommonsWare once said "A skilled developer will avoid using dialogs" (or something like that). And this is not a good use of a dialog. As I often say "This is programming, anything is possible" - yes, you can determine that, but coupling what image was last requested and what mp3 should be playing is also not a good thing.Grogshop
I agree with you on that , but then what is the best fix in this situation I am ready to use two threads but how to avoid adapter as it would be called twice as you have said its an expected behavior and hence the thread would be called twice also from the adapter.Upwards
Don't put threading inside adapter. Make an external call to Application context or Service and control starting threads. If someone already started downloading some mp3 or image, don't start it again.Grogshop
let us continue this discussion in chatUpwards

© 2022 - 2024 — McMap. All rights reserved.