Passing context to Handler

13,415

Solution 1

What if you create a subclass which extends Handler? That way you could pass any parameters you want.

But just out of curiosity, why does the Blossom object require the context object? It's usually best to separate your logic from GUI dependencies.

Solution 2

Create a class that extends Handler, and store a weak reference to the context. This will help prevent some memory issues.

public class SomeHandler extends Handler {

    // A weak reference to the enclosing context
    private WeakReference<Context> mContext;

    public SomeHandler (Context context) {
        mContext = new WeakReference<Context>(context);
    }

    public void handleMessage(Message msg) {

        // Get an actual reference to the DownloadActivity
        // from the WeakReference.
        Context context=mContext.get();
        ...
    }
}
Share:
13,415
Hani Honey
Author by

Hani Honey

Updated on June 04, 2022

Comments

  • Hani Honey
    Hani Honey almost 2 years

    Is it possible to pass arguments to an Android Handler?? I have two pieces of code.

    new Thread(){
            public void run(){
                for(;;){
                    uiCallback.sendEmptyMessage(0);
                    Thread.sleep(2000); //sleep for 2 seconds
                }
            }
        }.start();
    
    
        private Handler uiCallback = new Handler(){
        public void handleMessage(Message msg){
            //add a new blossom to the blossom ArrayList!!
            blossomArrayList.add(new Blossom(context, R.drawable.blossom));
        }
    };
    

    I of course get an error because the Handler method cannot see my context. This is probably because of this piece of code

    public BoardView(Context context){
        super(context);
    

    Context is not visible elsewhere, and I'm wondering if I can pass it as an argument to my Handler.

    EDIT: I am posting the two main pieces of code to answer a question about why my Blossom object needs context. I myself am not 100% sure >.> Maybe you could have a look and see what's going on.

    public class Blossom{
    private Bitmap blossom;
    private float blossomX = 0;
    private float blossomY = 0;
    private Random generator = new Random();
    
    public Blossom(Context context, int drawable)
    {
        blossom = BitmapFactory.decodeResource(context.getResources(), drawable); 
        blossomX = generator.nextInt(300);
    }
    
    public Bitmap getBitmap()
    {
        return blossom;
    }
    
    public float getBlossomX()
    {
        return blossomX;
    }
    
    public float getBlossomY()
    {
        return blossomY;
    }
    
    public void Fall(Canvas canvas, float boxY)
    {
        //draws the flower falling
        canvas.drawBitmap(blossom, blossomX,
                blossomY = blossomY+3 , null);
    
        //collision detection, currently not working after 
        //implementing random start location
    
        //if(blossomY + 29 == boxY)
        //{
            //canvas.drawBitmap(blossom,0,0,null);
        //}
    
    }
    }
    
    
    public class BoardView extends SurfaceView implements SurfaceHolder.Callback{
    Context mContext;
    
    Bitmap box = 
        (BitmapFactory.decodeResource
                (getResources(), R.drawable.box));
    
    private BoardThread thread;
    private float box_x = 140;
    private float box_y = 378;
    private float boxWidth = box.getWidth();
    private float boxHeight = box.getHeight();
    private ArrayList<Blossom> blossomArrayList = new ArrayList<Blossom>();;
    
    boolean mode = false;
    
    RectF boxRect = new RectF(box_x,box_y, box_x + boxWidth, box_y + boxHeight);
    
    public BoardView(Context context){
        super(context);
    
        //surfaceHolder provides canvas that we draw on
        getHolder().addCallback(this);
    
        // controls drawings
        thread = new BoardThread(getHolder(),this);
    
        //pass variables to instance of Blossom
        //for(int i = 0; i <= 3; i++)
        //{
            //blossomArrayList.add(new Blossom(context, R.drawable.blossom));
        //}
    
        new Thread(){
            public void run(){
                for(;;){
                    uiCallback.sendEmptyMessage(0);
                    Thread.sleep(2000); //sleep for 2 seconds
                }
            }
        }.start();
    
        //intercepts touch events
        setFocusable(true);
    
    }
    
    @Override
    
    public void onDraw(Canvas canvas){
        canvas.drawColor(Color.WHITE);  
    
    
        //draw box and set start location
        canvas.drawBitmap(box, box_x - (boxWidth/2), 
                box_y - (boxHeight/2), null);
    
        for(int i = 0; i<= 3; i++)
        {
            blossomArrayList.get(i).Fall(canvas, box_y);
        }
    
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event){
    
        if(event.getAction() == MotionEvent.ACTION_DOWN){
            if(boxRect.contains(event.getX(),event.getY())){
                mode = true;
            }
        }
    
        if(event.getAction() == MotionEvent.ACTION_MOVE) {
            if(boxRect.contains(event.getX(),event.getY())){
                mode = true;
            }
            if(mode == true){
                box_x = (int)event.getX();
                boxRect.set(box_x,box_y, box_x + boxWidth, box_y + boxHeight);
            }
    
        }
    
        if(event.getAction() == MotionEvent.ACTION_UP){
            mode = false;
        }
    
        invalidate();
    
        return true;
    }
    
    @Override
    public void surfaceChanged(SurfaceHolder holder, 
            int format, int width, int height ){
    
    }
    
    @Override
    public void surfaceCreated(SurfaceHolder holder){
        thread.startRunning(true);
        thread.start();
    }
    
    @Override
    public void surfaceDestroyed(SurfaceHolder holder){
        thread.startRunning(false);
        thread.stop();
    }
    
    private Handler uiCallback = new Handler(){
        public void handleMessage(Message msg){
            //add a new blossom to the blossom ArrayList!!
            blossomArrayList.add(new Blossom(context, R.drawable.blossom));
        }
    };
    
    
    }
    
  • Hani Honey
    Hani Honey about 13 years
    I have posted the rest of my code so you can see what is going on with the context. I honestly have no idea :(
  • Hani Honey
    Hani Honey about 13 years
    It was the only way I could figure out how to get a bitmap into my Blossom class, that's why.
  • kkudi
    kkudi about 13 years
    Well your Blossom constructor could just take the bitmap instead. But nevertheless, what you want can be achieved by just creating a new class say MyHandler which extends Handler and create a constructor public MyHandler(Context context) {....}
  • Hani Honey
    Hani Honey about 13 years
    Thank you - I just passed it the bitmap and it was fine :D Why didn't I do that in the first place...
  • hidd
    hidd almost 5 years
    Very useful. Thanks a lot.