0

I just came through a strange problem when using HandlerThread and Handlers (By Handlers i mean android.os.handler). I am trying to pass message from my Fragment to a separate Handler Thread. I just setup a handleMessage to handle message. But it is not called. I have got the looper for the handler thread after starting the thread using start()(after the looper is prepared).I have also checked that the handler got the message using hasMessage(). everything is fine. I am confused. kindly help me.My codes are below.

Fragment Code:

   package com.example.raaja.handlerone;

import android.app.Fragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;





/**
 * Created by Raaja on 08-12-2015.
 */
public class LoaderFragment extends Fragment {
    Button loaderButton;
    LoaderThread loadThread;
    Handler loaderThreadHandler;
    Handler loaderHandler;
    String[] queArray;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        loaderHandler = new Handler();
        loadThread = new LoaderThread("LoaderThread",loaderHandler);
         queArray = new String[]{"http://www.paynekillers.com/downloads/screens/17_screen05.jpg",
                "http://www.hdwallpapers.in/walls/jacob_frye_assassins_creed_syndicate-wide.jpg",
        "http://www.percivalconstantine.com/wp-content/uploads/2015/03/Tomb-Raider-Lara-Croft-Summit-2013.jpg",
        "http://orig00.deviantart.net/f904/f/2014/155/e/a/batman_arkham_knight_hd_wallpaper_1_by_rajivcr7-d7l19pt.jpg",
        "http://static5.gamespot.com/uploads/original/536/5360430/2753139-15774024117_9026e0a43c_o.jpg"};
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View loaderView = inflater.inflate(R.layout.loader_layout, container, false);
        this.loaderButton = (Button) loaderView.findViewById(R.id.proc_button);
        return loaderView;
    }

    @Override
    public void onResume() {
        super.onResume();



        loaderButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loadThread.start();
                Looper loop = loadThread.requestLooper();
                loaderThreadHandler = new Handler(loop);
                Message msg = Message.obtain(loaderThreadHandler, 1, queArray);
                msg.sendToTarget();


            }
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        loadThread.quit();
    }
}

HandlerThread

 package com.example.raaja.handlerone;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * Created by Raaja on 08-12-2015.
 */
public class LoaderThread extends HandlerThread implements Handler.Callback{
    Handler imageHandler;
    Map<Integer,String> queMap;
    HandlerActivity activity;

    public LoaderThread(String name, Handler handler) {
        super(name);
        imageHandler= handler;
        Log.d("inside : ", name);
    }

    Looper requestLooper(){

        Looper loop = this.getLooper();
        Log.d("In Thread : ", String.valueOf(loop.getThread().getName()));
        return loop.myLooper();
    }


    @Override
    public boolean handleMessage(Message msg) {
        String[] que = (String[]) msg.obj;
        queMap = new HashMap<Integer,String>();
        if(que != null){Log.d("",que[3]);}
        for (int i=0;i<=4; i++){
            String url = que[i];

            queMap.put(i,url);
            Log.d("1",url);
        }
        Random rand = new Random();
       String link = queMap.get(rand.nextInt(5));

        loadImages(link);
        return true;
    }

    void loadImages(final String url){
        Log.d("inside Load :","Inside Load");
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            final Bitmap image = BitmapFactory.decodeStream(connection.getInputStream());
            imageHandler.post(new Runnable() {
                @Override
                public void run() {
                    activity.loadImage(image, url);
                }
            });

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}
Raaja SN
  • 382
  • 3
  • 14
  • no, no ,no, what you need is: `ht = new HandlerThread("..."); ht.start(); h = new Handler(ht.getLooper()) {...` – pskink Dec 10 '15 at 17:57
  • @pskink thats what i have done. LoaderThread above i extended class HandlerThread. As you said i have done the same. Called loadThread = new LoaderThread(".."); on onCreate(). I have called loadThread.start(); and loaderThreadHandler = new Handler(looper);. I have tried calling new Handler(loadThread.getLooper()); Thats on my first version and i get the same result. – Raaja SN Dec 11 '15 at 08:19
  • no, you extended `HandlerThread`, you dont have to that, just follow my 3 steps – pskink Dec 11 '15 at 08:20
  • @pskink I just want to extend a new HandlerThread. I hope you are suggesting me to start a thread inside Fragment (innerThread). Is it so? If so what Difference does it make while extending it? – Raaja SN Dec 11 '15 at 08:26
  • start it right after you create it (in `Fragment#onCreate`) – pskink Dec 11 '15 at 08:30
  • @pskink Why is it so? Kindly tell me the difference. I just wanted to start the thread only when the button is clicked. I thought by doing so i will start the Thread only when i needed and did not waste resource? am i right? – Raaja SN Dec 11 '15 at 08:33
  • ok so start it when button is clicked, no difference – pskink Dec 11 '15 at 08:39
  • @pskink ok But my problem is not fixed? do you have any guess why handleMessage is not called? – Raaja SN Dec 11 '15 at 09:14
  • did you try to follow my 3 steps? – pskink Dec 11 '15 at 09:15
  • yes . I tried and as i said your steps is what i used when first codding this app. Then i decided to start the thread only when i needed. But the problem persists. i even tried calling handleMessage explicitly by loadThread.handleMessage(). The message is called but when it gets inside the network operation i got NetworkOnMainThread exception. – Raaja SN Dec 11 '15 at 09:29
  • so post your code how you are sending the messages / posting runnables – pskink Dec 11 '15 at 09:31
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/97601/discussion-between-raaj-foru-and-pskink). – Raaja SN Dec 11 '15 at 09:35

1 Answers1

0

ANSWER TO MY QUESTION:

I am able to send messages and I can receive message to my handleMessage() from the other thread. I have already extended the HandlerThread class and implemented Handler.Callback for my Thread class. So I just used the below version to instantiate a Handler passing the thread as Callback(as it implements the Handler.Callback it was accepted as callback). I hope it helps. If you are confused, read the code carefully. Thank you.

Handler myHandler = new Handler(myThread.getLooper(),myThread);
Raaja SN
  • 382
  • 3
  • 14