2

2 つの単純なクラスがあります。

public class MainActivity extends Activity {
    NetworkTask task;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        [...]       
        task = new NetworkTask();
        task.execute();
    }

public void myClickHandler(View view) {
    switch(view.getId()) {
        case R.id.button1:
            // Why this line crash?
            task.connection("127.0.0.1");
        break;
        }
    }
}

public class NetworkTask extends AsyncTask<String, Void, String> {
    Socket sock;
    volatile boolean running = true;

    public int connection(String url){
        try{
            sock = new Socket(url, 4567)
        }
        catch (IOException ex){
            Logger.getLogger(NetworkTask.class.getName()).log(Level.SEVERE, null, ex);
            return -1;
        }
    }

    public String doInBackground(String... strings) {

        // If I do this, it works well
        //connection(127.0.0.1);

        while(running)
        {
            [...]
        }

        return null;
    }   
}

AsyncTask メソッドの外部から接続メソッドを呼び出すとコメントしたように、アプリは特に « sock = new Socket(...) » 行でクラッシュします。ただし、AsynTask メソッド内で接続呼び出しが行われると、ソケットが作成されます。理由がわかりません。

何が起こっていますか?

ありがとう。

4

1 に答える 1

4

それはあなたがするときだからです

task.connection("127.0.0.1");

あなたはまだメイン (UI) スレッドで作業しています - AsyncTask を適切に使用していません。代わりに、通常のクラスのように使用しているため、NetworkOnMainThreadException新しい Android バージョンを取得できます。

ただし、から呼び出すdoInBackground()場合は、AsyncTask を介して開始したことを意味しexecute、作業はのスレッドで行われ、すべてが正常に機能します。

ネットワーク以外のことをしている場合でも、外部から呼び出すことができることに注意してください。ただし、AsyncTask は 1 回しか実行されないため、AsyncTask を外部にできるだけ依存させないようにすることをお勧めします。さらに作業を行う場合は、新しいインスタンスを作成する必要があります。つまり、setter メソッドなどに依存している場合は、それらのメソッドを再度呼び出す必要があり、この単純なクラスが必要以上に複雑になります。

AsyncTask の使用方法のポイント説明としては、これは非常に優れたソースです。もちろん公式ドキュメントも。

于 2013-02-09T21:11:29.610 に答える