Android Runnable チュートリアルと実例集

このクラスでは、Runnable インターフェースを見て、その使い方の例を見ます。

Runnable とは?

javaでは、Runnableというインターフェースは、基本的に実行可能なコマンドを抽象化したものです

javaやandroidの低レベルの同時実行構成要素として、Thread`クラスについて話しました。

もうひとつの構成要素は Runnable です。これは Java API に由来するインターフェースで、Java の thread インスタンスや、この Runnable を処理する他のクラスによって実行されることを意図したコードを指定し、カプセル化することを目的としています。

これはインターフェイスで、java.langパッケージで定義されており、私たちが実装しなければならないrun()という抽象メソッドを持っています。

package java.lang;
public interface Runnable{
    public abstract void run();
}

使い方

Runnable インターフェースは Threadsでコードを実行するために広く使われています。 Runnable インターフェースには、run() という抽象メソッドがあります。

public abstract void run ()

通常,クラスが Runnable インターフェースを実装している場合は,必ずこのメソッドを実装します.
このメソッドが呼ばれると、クラスのコードのアクティブな部分の実行が開始されます。

例えば、スレッドのメカニズムとして Runnable を使いたいとしましょう。まずインターフェイスを実装します。そして、run()メソッドの実装を行います。

public class MyRunnable implements Runnable {
    public void run(){
        Log.d("Generic","Running in the Thread " +
        Thread.currentThread().getId());
    }
}

これで、私たちの Runnable サブクラスは Thread に渡され、同時実行ラインで独立して実行されるようになります。

    Thread thread = new Thread(new MyRunnable());
    thread.start();

以下のコードでは、基本的に Runnable サブクラスを作成し、それが run() を実装するようにしています。
次のコードでは、基本的にRunnableサブクラスを作成して、run()メソッドを実装し、スレッドに渡されて実行できるようにしています。

Runnable インターフェース 間接的なサブクラス

Runnable にはたくさんのサブクラスがありますが、ここではよく使われるものだけをリストアップします。

No. クラス 説明
このクラスは、Runnable インターフェースを実装しています。Thread クラスは、Runnable の抽象メソッドである run() を、Thread の具象メソッドである run() を呼び出すことで利用します。その run() メソッドは、内部で Runnable の抽象 run() メソッドを呼び出します。
TimerTaskRunnable インターフェースを実装しており、TimerTask が実行するタスクは run()` メソッドで指定されます。
3. このクラスは Runnable インターフェースを実装した RunnableFuture インターフェースを実装しています。

それでは、いくつかの例を見てみましょう。

アンドロイドのRunnableの例をステップバイステップで見てみましょう。

これはアンドロイドの例です。アンドロイドは明らかにJavaを使用しており、RunnableインターフェースはAPIレベル1から存在しています。

以下のように、RunnableServiceと組み合わせて使うことができます。

public class MyService extends Service implements Runnable{}

これにより、抽象的な run() メソッドをそのクラス内に実装することになります。

 @Override
    public void run() {
    }

また、これが Service であることから、Service の抽象メソッドである onBind() もオーバーライドする必要があります。

 @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

ServiceはAndroidのコンポーネントで、ライフサイクルコールバックを持っています。その1つがonCreate()で、Service`が作成されるたびに発生するメソッドです。

このメソッドは、「サービス」が作成されるたびに発生しますので、私たちは「スレッド」を作成して起動したいと考えています。

@Override
    public void onCreate() {
        super.onCreate();
        Thread myThead=new Thread(this);
        myThead.start();
    }

そして、1秒ごとにいくつかのメッセージをログに記録したいとしたら、run()メソッドの中に次のコードを追加します。

        while (true)
        {
            try{

                Log.i(MY_TAG,"Distance in Light Years : "+spaceship_distance);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

そして、インスタンス変数として、以下のコードを onCreate() メソッドの上に追加します。

public static String MY_TAG="MY_SERVICE";
private int spaceship_distance=0;

以上、AndroidでのRunnableの使用例を紹介しました。もし、Serviceを実際に走らせたい場合は、以下のようにします。

  1. マニフェストに Service を登録する。

```java

```

MyService<code>ではなく、</code>Service`の名前を必ず指定してください。</code></pre>
<ol start="2">
<li>
<ol start="2">
<li><code>MainActivity</code> で <code>Service</code> を起動する。</li>
</ol>
</li>
</ol>
<!-- 12 -->
<pre><code>```java
Intent i=new Intent(this,MyService.class);
startService(i);
```

以上、servicesを使ったandroid Runnableインターフェースの例でした。

なお、Runnableをこのように使うこともあります。

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

        new Thread(new Runnable() {
            @Override
            public void run() {
                ArrayList<Song> songs = scanSongs(ScanMusicService.this);
                LogUtils.d(songs);
                ToastUtils.showLongToast(songs.toString());
            }
        }).start();

    }

Runnable クイックサンプル

(a). HttpURLConnectionRunnableを使ってHTTP GET`を実行する方法

HttpURLConnectionはネットワーククラスで、HTTP GET`のリクエストを実行することができます。

一方、Runnable は、バックグラウンド・スレッドで HTTP GET リクエストを実行するためのインターフェイスです。

まずは Runnable インターフェースを実装して、run() メソッドをオーバーライドすることになります。

HTTP GET を実行するのは、この run()` メソッドの内部です。

public class UrlRequest implements Runnable {
    ......
 @Override
    public void run() {
        try {
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            InputStream stream = connection.getInputStream();
            int responseCode = connection.getResponseCode();
            ByteArrayOutputStream responseBody = new ByteArrayOutputStream();
            byte buffer[] = new byte[1024];
            int bytesRead = 0;
            while ((bytesRead = stream.read(buffer)) > 0) {
                responseBody.write(buffer, 0, bytesRead);
            }
            listener.onReceivedBody(responseCode, responseBody.toByteArray());
        }
        catch (Exception e) {
            listener.onError(e);
        }
    }
}

これが完全なクラスです。

import android.support.annotation.NonNull;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class UrlRequest implements Runnable {

    public interface Listener {

        void onReceivedBody(int responseCode, byte body[]);
        void onError(Exception e);
    }

    public interface RequestFactory {

        @NonNull
        UrlRequest makeRequest(URL url, Listener listener);
    }
    private static RequestFactory factory = new RequestFactory() {
        @NonNull
        @Override
        public UrlRequest makeRequest(URL url, Listener listener) {
            return new UrlRequest(url, listener);
        }
    };

    private URL url;
    private Listener listener;

    public static UrlRequest makeRequest(URL url, Listener listener) {
        return factory.makeRequest(url, listener);
    }

    public static void setFactory(RequestFactory newFactory) {
        factory = newFactory;
    }

    public UrlRequest(URL url, Listener listener) {
        this.url = url;
        this.listener = listener;
    }

    @Override
    public void run() {
        try {
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            InputStream stream = connection.getInputStream();
            int responseCode = connection.getResponseCode();
            ByteArrayOutputStream responseBody = new ByteArrayOutputStream();
            byte buffer[] = new byte[1024];
            int bytesRead = 0;
            while ((bytesRead = stream.read(buffer)) > 0) {
                responseBody.write(buffer, 0, bytesRead);
            }
            listener.onReceivedBody(responseCode, responseBody.toByteArray());
        }
        catch (Exception e) {
            listener.onError(e);
        }
    }
}