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

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

ただいまの
回答率

87.34%

ViewPagerのAdapter内のinstantiateItem内でreturnするタイミングを遅らせたい

解決済

回答 2

投稿 編集

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

score 100

お世話になります。

表題ではわかりづらいかと思いますがPagerAdapterのinstantiateItem内の処理が全て完了したタイミングで値を返したいのですがうまくできません

そもそもこの方法を探し出した経緯がViewPager内5ページの内容をPHPが吐いたXMLを読み込んでそれをパースし、Viewにセットしたいのですが各ページにしっかりとデータは反映するのですがページ表示直後だとViewPagerの1ページ目と2ページ目が表示されません
ViewPagerをスクロールし表示されないページから2ページ離れて再度該当ページに戻るとしっかり表示されるのですが読み込み直後だけ表示されていないのでXMLの読み込みとパースがinstantiateItemのreturnに間に合っていないのかと思い今に至りました
以下ソースです

public Object instantiateItem(View collection, final int position) {
        llv = new LinearLayout(mContext);
        llv.setOrientation(LinearLayout.VERTICAL);
        gl = (Globals) mContext.getApplicationContext();

        new Thread(new Runnable(){
            @Override
            public void run(){
                try{
                    URL url = new URL( URL );
                    Log.d("URL1212",url.toString());
                    HttpURLConnection con = (HttpURLConnection)url.openConnection();
                    str = InputStreamToString(con.getInputStream());
                    Log.d("xml",str);

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

            }
        }).start();

        while(str !=null){
            //xmlparse開始
            XmlPullParser xpp = Xml.newPullParser();
            try{
                xpp.setInput(new StringReader(str));
            }catch (XmlPullParserException e){

            }
//                    XML解析
            try {
                int eventType;
                eventType = xpp.getEventType();

                final LinearLayout llh = new LinearLayout(mContext);
                llh.setOrientation(LinearLayout.HORIZONTAL);

                while (eventType != xpp.END_DOCUMENT) {
                    if((eventType == xpp.START_TAG)){
                        if(("DateTitle"+position).equals(xpp.getName())){
//                                    llv = new LinearLayout(mContext);
//                                    llv.setOrientation(LinearLayout.VERTICAL);
                            final TextView tv = new TextView(mContext);
                            final String txt = xpp.nextText();
                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    tv.setTextSize(12);
                                    tv.setBackgroundColor(Color.parseColor("#d3d3d3"));
                                    tv.setText(txt);
                                    llh.addView(tv);
                                }
                            });
                        }else if(("DateData"+position).equals(xpp.getName())){
                            final TextView tv = new TextView(mContext);
                            final String txt = xpp.nextText();
                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    tv.setTextSize(18);
                                    tv.setText(txt);
                                    llh.addView(tv);
                                    llv.addView(llh);
                                }
                            });
                        }
                    }

                    eventType = xpp.next();
                }
            }catch (Exception e){
                Log.d("XmlPullParser", String.valueOf(e));
            }
            ((ViewPager) collection).addView(llv,0);
            //strに値が入ったら1回だけまわってループを脱出
            break;
        }
    return llv;
    }

知識がなさ過ぎて原因究明もまともにできておりません故他に原因等ございましたらご教授頂けますと幸いでございます

よろしくお願いします

//-------追記---------//

public Object instantiateItem(View collection, final int position) {
        llv = new LinearLayout(mContext);
        llv.setOrientation(LinearLayout.VERTICAL);
        gl = (Globals) mContext.getApplicationContext();

        new Thread(new Runnable(){
            @Override
            public void run(){
                try{
                    URL url = new URL("http://153.149.37.82/Eigyo_Test/xml/detail.php?position=" + position + "&search="+ gl.ProspectId +"&comcode=" + gl.ComCode + "&logid=" + gl.tID );
                    Log.d("URL1212",url.toString());
                    HttpURLConnection con = (HttpURLConnection)url.openConnection();
                    String str = InputStreamToString(con.getInputStream());
                    Log.d("xml",str);

                    while(str !=null){
                        //xmlparse開始
                        XmlPullParser xpp = Xml.newPullParser();
                        try{
                            xpp.setInput(new StringReader(str));
                        }catch (XmlPullParserException e){

                        }
//                    XML解析
                        try {
                            int eventType;
                            eventType = xpp.getEventType();

                            final LinearLayout llh = new LinearLayout(mContext);
                            llh.setOrientation(LinearLayout.HORIZONTAL);

                            while (eventType != xpp.END_DOCUMENT) {
                                if((eventType == xpp.START_TAG)){
                                    if(("DateTitle"+position).equals(xpp.getName())){
//                                    llv = new LinearLayout(mContext);
//                                    llv.setOrientation(LinearLayout.VERTICAL);
                                        final TextView tv = new TextView(mContext);
                                        final String txt = xpp.nextText();
                                        handler.post(new Runnable() {
                                            @Override
                                            public void run() {
                                                tv.setTextSize(12);
                                                tv.setBackgroundColor(Color.parseColor("#d3d3d3"));
                                                tv.setText(txt);
                                                llh.addView(tv);
                                            }
                                        });
                                    }else if(("DateData"+position).equals(xpp.getName())){
                                        final TextView tv = new TextView(mContext);
                                        final String txt = xpp.nextText();
                                        handler.post(new Runnable() {
                                            @Override
                                            public void run() {
                                                tv.setTextSize(18);
                                                tv.setText(txt);
                                                llh.addView(tv);
                                                llv.addView(llh);
                                            }
                                        });
                                    }
                                }

                                eventType = xpp.next();
                            }
                        }catch (Exception e){
                            Log.d("XmlPullParser", String.valueOf(e));
                        }

                    llv.postInvalidate();

                        break;
                    }

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

        ((ViewPager) collection).addView(llv,0);
    return llv;
    }
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

0

推測通り最初の処理ではリクエストに対するレスポンスが帰ってきていないので表示されることはありません。
そのあと表示されるのはstrはフィールド変数だからです。strは一度でもレスポンスが帰ってくるとnullじゃなくなります。そうなると実際に表示されているViewは今のリクエストではなく以前のリクエストに対するレスポンスを表示するだけなので表示がずれているはずです。

改善するにはwhile文の処理もThreadの中に移動し、strをローカル変数にする必要があります。
また、breakの直前でllv.postInvalidateを呼ぶと改善する必要がありそうです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/07/15 18:34

    いつもご回答ありがとうございます!
    ご回答いただいた内容で修正すると全件表示はしたのですが1ページ目の内容が2ページ目の内容と連なって2ページ目に表示されます、、、

    念のため改善後のソースを質問文に追記します、、

    お手間とらせてすみません

    キャンセル

  • 2016/07/15 18:48

    それはllvもフィールド変数だからだと考えられます。

    また、ここまでやるのであればLinearLayoutを継承したクラスを作った方が良さそうです。

    キャンセル

  • 2016/07/15 19:05

    llv をローカル変数で宣言することで解決できました!
    ありがとうございます!
    もしよろしければでいいのですが後者を行うメリットだったり意図だったり理解のヒントになるようなキーワード等教えてもらえませんか?
    ここ1カ月javaもといandroidアプリの開発を手探りながらも業務で行っているのですが一難去ってまた一難な状態で、、、基礎知識が圧倒的に足りないのを痛感しております、、、
    もしよかったらここは抑えといたほうがいいよ等のことがあれば教えてくださるとうれしい限りです
    ご迷惑であれば申し訳ございません

    キャンセル

  • 2016/07/15 20:18

    Activity、Fragmentに全ての処理を書いていませんか?
    確かに、全ての処理をこれらのクラスに書くことはできますが、クラスの行数や機能、役割等が肥大化し保守性が低下します。そこでクラスを分ける必要が出てきます。

    LinearLayoutではなくListViewを使うべきかなと思います。
    1:Threadで書いているクラスをAsyncTaskLoaderに書き換えて別クラスにする。
    2:1のクラスはリクエストを送り、レスポンスを解析し画面に表示する為のデータのリストを作成する。
    3:Activityから1のローダーを呼びして表示するデータのリストを取得する。
    4:ArrayAdapterを継承したクラスを作成し、ListViewに渡す。

    キャンセル

0

new Thread(new Runnable(){
    public void run(){
        try{
            ...
            HttpURLConnection con = (HttpURLConnection)url.openConnection();
            str = InputStreamToString(con.getInputStream());
            ...
        }catch (Exception ex){
            ...
        }
    }
}).start();
while(str !=null){
}


(strの初期値がnullを前提として)whileの判定までに(通信が完了せずに) str == null の場合に、何も表示しない空のPageがreturnされます。
再度同じページが指定された時には、前回の通信結果を元にパースを行って画面表示しているのではないでしょうか。
暫定対処ですが、「while(str !=null){」の前に、下記を追加したらどうなりますか。

while(str == null) {
   // 何もせずに待つ
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/07/15 18:49

    ご回答ありがとうございます!
    ご指摘いただいた箇所ともう一点ViewPagerにaddViewしているところも怪しかったのでそこも
    while(llv == null) {
    // 何もせずに待つ
    }
    while(llv != null){
    ((ViewPager) collection).addView(llv,0);
    }

    とやってみましたが駄目でした、、、

    キャンセル

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

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

関連した質問

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