質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.37%

PHPが出力したXMLをもとにSpinnerの選択肢を作成したい

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 1,157

hanhunhun

score 100

毎度お世話になってます。

PHPが出力したXMLを解析し、そのデータをarrayListに格納しAdapterを作成してSpinnerの選択肢を作成しようと思っているのですが下記コードだと選択肢はできても選択ができず困っております。

Handler handler = new Handler();

    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_week);

        Spinner sp = (Spinner)findViewById(R.id.spinner);

        final ArrayList arrayList = new ArrayList<String>();

        new Thread(new Runnable(){
            @Override
            public void run(){
                try{
                    URL url = new URL("XMLをはくPHPソースのURL");
                    HttpURLConnection con = (HttpURLConnection)url.openConnection();
                    String str = InputStreamToString(con.getInputStream());
                    XmlPullParser xpp = Xml.newPullParser();
                    try{
                        xpp.setInput(new StringReader(str));
                    }catch (XmlPullParserException e){
//                        Log.d("XmlPullParser", "Error");
                    }

//                    XML解析
                    try {
                        int eventType;
                        eventType = xpp.getEventType();
                        while (eventType != xpp.END_DOCUMENT) {
                            if((eventType == xpp.START_TAG)){
//                                
                                if("teamName".equals(xpp.getName())){

                                    arrayList.add(xpp.nextText());

                                }

                            }
                            eventType = xpp.next();
                        }

                        handler.post(new Runnable() {
                            @Override
                            public void run() {

                            }
                        });
//

                    }catch (Exception e){

                    }
                }catch (Exception ex){
                    System.out.println(ex);
                }


            }
        }).start();
        ArrayAdapter<String> ad = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, arrayList);
        ad.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        sp.setAdapter(ad);
    }

arrayList.addで任意の文字列(”テスト”)等を追加すると正常にSpinnerは動作するのですが上記コードだと選択肢が選択できない状態になります。

わかりにくい質問かもしれませんがよろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

0

XMLをパースした後に下記の処理移動させるといいと思いますよ。

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        ArrayAdapter<String> ad = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, arrayList);
        ad.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        sp.setAdapter(ad);
    }
});

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/27 11:56

    すみません、、、ものすごく初歩的なことをわかってなかったみたいです、、、お恥ずかしい
    問題が解決しました!
    ちなみに差し支えなければ自己解決で提示しているコードは問題ないでしょうか?
    後学の参考にしたいです!

    キャンセル

  • 2016/05/27 12:25

    コードは問題無いと思います。
    今回の原因はAdapterが保持するArrayListに対してAdapterを経由せずにArrayListに直接要素を追加したため、Adapterは要素が増えたことに気づけませんでした。

    対策としては2つあります。
    ・自己解決の通りAdapterに要素を追加すること。
    ・dekaakiさんの回答の通りArrayListに要素を追加し、Adapter#notifyDataSetChangedを呼ぶことでAdapterに要素の変更を通知すること。

    私はスピナーは通信が正常に終わらない限り使い物にならないと思っていたので、通信が終わった後にAdapterを作りセットする方法を提案しました。

    キャンセル

  • 2016/05/28 09:16

    なるほど、、
    ということはマルチスレッドはUIスレッドの処理の途中に処理を差し込むのではなく同時進行で処理を行う、だからマルチスレッドの処理が中途半端なままUIスレッドでAdapterを作って中途半端なArrayListをセットしていたからSpinnerが正常に動かなかったんですね、、
    大変参考になりました!ありがとうございます!

    キャンセル

0

確かadapterの元となったコレクションを直接操作した場合は
notifyDataSetChangedを呼び出してあげないと変更した内容が正しく伝わらないと記憶してます。

参考プログラムを動かすと確かにリストは作成されて、画面上も表示はされるがタップして選択すると選択状態は解除されてました。

そこでリストの設定が終了した時点でnotifyDataSetChangedを呼び出してあげると正しく動作するようになりました。
また、Activityで非同期処理を行い、UIスレッドに戻って何かしたい場合はHandlerを使うのもいいですがUIスレッドで実行してもらうためのrunOnUiThreadメソッドがActivityにはありますのでそれを使用するようにしてみました。
こんな感じでどうでしょう?

new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                }

                arrayList.add("test1");
                arrayList.add("test2");
                arrayList.add("test3");
                arrayList.add("test4");
                arrayList.add("test5");

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Spinner sp = (Spinner) findViewById(R.id.spinner);
                        ((ArrayAdapter<String>)sp.getAdapter()).notifyDataSetChanged();
                    }
                });

            }
        }).start();

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/27 10:11

    回答ありがとうございます!
    このコードを試してみたんですがspinnerに値がセットできませんでした、、、
    handlerとrunOnUiThreadの違いについても掘り下げて学習します!

    キャンセル

0

結局のところこの方法でうまく動作しました

Handler handler = new Handler();

    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_week);

        Spinner sp = (Spinner)findViewById(R.id.spinner);

        final ArrayAdapter<String> ad = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item);

        new Thread(new Runnable(){
            @Override
            public void run(){
                try{
                    URL url = new URL("XMLをはくPHPのURL");
                    HttpURLConnection con = (HttpURLConnection)url.openConnection();
                    String str = InputStreamToString(con.getInputStream());
                    XmlPullParser xpp = Xml.newPullParser();
                    try{
                        xpp.setInput(new StringReader(str));
                    }catch (XmlPullParserException e){
                        Log.d("XmlPullParser", "Error");
                    }

//                    XML解析
                    try {
                        int eventType;
                        eventType = xpp.getEventType();
                        while (eventType != xpp.END_DOCUMENT) {
                            if((eventType == xpp.START_TAG)){

                                if("teamName".equals(xpp.getName())){

                                    final String txt = xpp.nextText();

                                    handler.post(new Runnable() {
                                        @Override
                                        public void run() {

                                            ad.add(txt);

                                        }
                                    });



                                }

                            }
                            eventType = xpp.next();
                        }

//

                    }catch (Exception e){
                        Log.d("error",e.getMessage());
                    }
                }catch (Exception ex){
                    System.out.println(ex);
                }


            }
        }).start();


        ad.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        sp.setAdapter(ad);

        sp.setOnItemSelectedListener(new spTeamListener());
    }

変更点は一度ArrayListに格納したデータをAdapterにセットしていたところを直でAdapterに格納するようにしたところうまく動作しました。

ご回答いただきありがとうございました

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る