1

いくつかの投稿を読み、ASYNCTASKに関する開発者ページを読んだ後、次のコードを思いつき、ボタンに割り当てました。

private class TalkToServerTask extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... params) {
        String response = "";
        try {
            InetAddress serverAddr = InetAddress.getByName(params[0]);
            Socket s = new Socket(serverAddr, Integer.valueOf(params[1]));

            PrintWriter out = new PrintWriter(new BufferedWriter(
                    new OutputStreamWriter(s.getOutputStream())), true);

            // WHERE YOU ISSUE THE COMMANDS

            out.println(params[2]);
            // BufferedReader input = new BufferedReader(
            // new InputStreamReader(s.getInputStream()));

            DataInputStream dataInputStream = null;
            dataInputStream = new DataInputStream(s.getInputStream());
            st = dataInputStream.readLine().toString();
            // String st = s.readLine();
            // st = input.readLine();
            // read line(s)

            s.close();
            return st;

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

    @Override
    protected void onPostExecute(String result) {
        serverresponse = result;
    }

}

ボタンがクリックされると、ASyncTaskが「getDomains」という単語をサーバーで実行されているコンソールアプリに送信し、サーバーがこれに基づいて動作し、電子メールサーバーで作成されたドメインのリストを含む文字列を送り返すという考え方です。

サーバーがコマンド「getdomains」を受信して​​いることを確認しました。サーバーは、パイプで区切られたドメインの文字列で応答します。ただし、問題は、ソケットトランザクションの結果をポップアップ表示するようにトーストを設定したのに、トーストに何も表示されないことです。もう一度ボタンを押すと、トーストにドメインのリストが表示されます。私には、ソケットが最初に空を返しているように見えます

ボタンコードは次のとおりです。

case R.id.btnDomains:
            SharedPreferences sp = PreferenceManager
                    .getDefaultSharedPreferences(this);
            IpAddress = sp.getString("ipaddress", "0.0.0.0");
            Serverport = sp.getString("tcpport", "12345");
            buttonpressed = "domains";
            // TalkToServerTask task = new TalkToServerTask();
            new TalkToServerTask().execute(IpAddress, Serverport, "getDomains");

            Intent buttonActivity = new Intent(MainActivity.this, Rules.class);
            buttonActivity.putExtra(MainActivity.DOMAINLIST, serverresponse);

            Toast.makeText(getApplicationContext(), serverresponse,
                    Toast.LENGTH_SHORT).show();

変数「serverresponse」は、最初は空を示していますが、サーバーのリストを示しています。

4

3 に答える 3

3

Thepoosh が述べたように、AsyncTask は別のスレッドで動作しています。

したがって、スレッドは実行中であり、最初にボタンを押したときにまだ結果を取得していません。

onPostExecute メソッドでデータを表示する必要があります。また、コンテキストを AsyncTask に渡す必要があります。

public TalkToServerTask(Context context)  {
    this.context = context;
}

@Override
protected void onPostExecute(String result) {
    Intent buttonActivity = new Intent(context, Rules.class);
    buttonActivity.putExtra(MainActivity.DOMAINLIST, result);

    Toast.makeText(context.getApplicationContext(), result, Toast.LENGTH_SHORT).show();
}
于 2012-05-28T07:29:48.447 に答える
0

AsynTaskUI スレッドとは別のスレッドで実行されます。したがって、2 つのスレッドが並行して実行されます。メイン UI スレッドでトーストにリストを表示しようとしている間、AsynTaskはまだリストをフェッチする準備をしているか、独自のスレッドでソケットを作成している可能性があります。したがって、リスト データはまだ空です。

postexecuteメソッドはAsynctaskメインの UI スレッドで実行されるため、UI を安全かつ正確に更新できます。

于 2012-05-28T07:39:33.723 に答える
0

コードを少し変更するだけで、

この 3 行を移動する必要があります。

Intent buttonActivity = new Intent(MainActivity.this, Rules.class); 
buttonActivity.putExtra(MainActivity.DOMAINLIST, serverresponse); 
// and also the line to startActivity() as well.
Toast.makeText(getApplicationContext(), serverresponse, 
                    Toast.LENGTH_SHORT).show(); 

あなたSwitch..caseからあなたが書いonPostExecuteた場所へAsyncTaskserverresponse = result

これは、Swtich で実行している間に AsyncTask が別のスレッドで実行されるためです... AsyncTask が終了するまで次のコード行が実行されないのは好ましくないため、依存するすべてのコードは Task の onPostExecute に記述する必要があります。 .

于 2012-05-28T07:28:12.720 に答える