RabbitMQ的Android端接收

本次做的項目,有一部分是通過RabbitMQ來傳輸的實時數據。然後我這Android端就需要研究怎麼接收。以前用的volley什麼的,都是用http通訊的,這個稍微不太一樣,採用的消息隊列的方式,生產者與消費者的設計模式,觀察者模式。有次面試就掛這了TT。

看了下RabbitMQ,可以服務端上可以設置爲

  • 工作隊列(Work queues)這種模式下,只有一個消息隊列,但是有多個消費者,這樣每個任務只會被一個消費者處理

  • 訂閱發佈模式(Publish/Subscribe)這種模式下,會有多個隊列,每個隊列都有一個消費者

我們項目中服務端應該用的就是Publish/Subscribe這種。 
這裏寫圖片描述 
從官網盜圖

除了生產者、消費者、消息隊列這些東西外,還多了一個X,這個X指的是Exchanges(可以翻譯成交換機)。

在這種模式下,生產者不直接把信息發送給消息隊列,而是隻發送給Exchanges,由Exchanges轉發給每個消息隊列。

Exchanges收到信息後會進行一些處理,比如這個消息我都應該發送給哪些隊列,還是隻發送給一個隊列,還是應該丟棄這個消息。這樣每個消息隊列從Exchanges收到的東西可能都不一樣,收到的消息都是根據每個消息隊列的需求定製的。比如我們項目分爲了油車和電車兩種,可以有兩個消息隊列,一個消息隊列只收油車數據,一個只收電車數據。這樣根據需要,我在客戶端這可以指定我只接受電車的數據了,我就可以從只收電車數據的這個消息隊列裏取了。

然後開始實現: 
https://www.cloudamqp.com/blog/2015-07-29-rabbitmq-on-android.html 
在這發現了一篇好教程,直接教我怎麼在Android上實現。

代碼不多,很容易就可以實現。 
我把代碼精簡了下,因爲我這只需要從服務器接收數據就可以了,所以把publish的代碼刪了

主要流程如下:

  1. 設置連接參數setupConnectionFactory
  2. 創建一個用於從線程中接收數據來更新UI的handler
  3. 啓動一個訂閱者線程,創建一個隊列,將其bind到參數中指定的Exchanges上,並根據傳入的routingKey路由關鍵字來從Exchanges中接收指定類型的消息數據。
  4. 之後創建消費者consumer從消息隊列中循環請求數據。
package edu.hrbeu.ice.rabbitmqclient;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;

import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

public class MainActivity extends AppCompatActivity {

    ConnectionFactory factory = new ConnectionFactory();
    Thread subscribeThread;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //連接設置
        setupConnectionFactory();

        //用於從線程中獲取數據,更新ui
        final Handler incomingMessageHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                String message = msg.getData().getString("msg");
                TextView tv = (TextView) findViewById(R.id.textView);
                Date now = new Date();
                SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss");
                tv.append(ft.format(now) + ' ' + message + '\n');
                Log.i("test", "msg:" + message);
            }
        };
        //開啓消費者線程
        subscribe(incomingMessageHandler);
    }

    /**
     * 連接設置
     */
    private void setupConnectionFactory() {
        factory.setHost("server url");
        factory.setPort(5671);
        factory.setUsername("guest");
        factory.setPassword("guest");
    }

    /**
     * 消費者線程
     */
    void subscribe(final Handler handler) {
        subscribeThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        //使用之前的設置,建立連接
                        Connection connection = factory.newConnection();
                        //創建一個通道
                        Channel channel = connection.createChannel();
                        //一次只發送一個,處理完成一個再獲取下一個
                        channel.basicQos(1);

                        AMQP.Queue.DeclareOk q = channel.queueDeclare();
                        //將隊列綁定到消息交換機exchange上
                        //                  queue         exchange              routingKey路由關鍵字,exchange根據這個關鍵字進行消息投遞。
                        channel.queueBind(q.getQueue(), "amq.fanout", "chat");

                        //創建消費者
                        QueueingConsumer consumer = new QueueingConsumer(channel);
                        channel.basicConsume(q.getQueue(), true, consumer);

                        while (true) {
                            //wait for the next message delivery and return it.
                            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
                            String message = new String(delivery.getBody());

                            Log.d("", "[r] " + message);

                            //從message池中獲取msg對象更高效
                            Message msg = handler.obtainMessage();
                            Bundle bundle = new Bundle();
                            bundle.putString("msg", message);
                            msg.setData(bundle);
                            handler.sendMessage(msg);
                        }
                    } catch (InterruptedException e) {
                        break;
                    } catch (Exception e1) {
                        Log.d("", "Connection broken: " + e1.getClass().getName());
                        try {
                            Thread.sleep(5000); //sleep and then try again
                        } catch (InterruptedException e) {
                            break;
                        }
                    }
                }
            }
        });
        subscribeThread.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        subscribeThread.interrupt();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129

源碼地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章