1

フラグメントは下部のナビゲーション バーの一部であり、これまでのところナビゲーション部分は良好です。しかし、fragment1 から fragment2 にデータを渡そうとすると、アプリがクラッシュします。また、この次のリンクでGoogleが提供する例を使用しています

次のコードを使用すると、android studio から非推奨の警告が表示されます。

@Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

したがって、以下のACTIVITYの代わりにCONTEXTを使用していますが、クラッシュするコードは次のとおりです。

主な活動

import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import com.br.tron.bottombar.RadioFragment;
import com.br.tron.bottombar.StreamFragment;
import com.br.tron.bottombar.InfoFragment;

public class MainActivity extends AppCompatActivity implements RadioFragment.OnNameSetListener {

    BottomNavigationView bottomNavigationView;
    private Fragment fragment;
    private FragmentManager fragmentManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragmentManager = getSupportFragmentManager();
        fragment = new RadioFragment();
        final FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.main_container, fragment).commit();

        bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottomNavigationBar);
        bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener(){
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {

                switch (item.getItemId()) {
                    case R.id.nav_button_one:
                        fragment = new RadioFragment();
                        break;
                    case R.id.nav_button_two:
                        fragment = new StreamFragment();
                        break;
                    case R.id.nav_button_three:
                        fragment = new InfoFragment();
                        break;
                }
                final FragmentTransaction transaction = fragmentManager.beginTransaction();
                transaction.replace(R.id.main_container, fragment).commit();
                return true;
            }
        });
    }

    public void performStreamClick(){
        View view = bottomNavigationView.findViewById(R.id.nav_button_two);
        view.performClick();
    }

    @Override
    public void setUrl(String url) {
        StreamFragment frag=(StreamFragment) getSupportFragmentManager().findFragmentByTag("frag");
        frag.getUrl(url);
    }
}

RadioFragment(データが存在するFragment1)

import android.app.Activity;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

public class RadioFragment extends Fragment implements Button.OnClickListener  {

    Button buttonman;
    View rootView;
    String url;
    Activity a;
    OnNameSetListener onNameSetListener;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof Activity) {
            a = (Activity) context;
            try{
                onNameSetListener=(OnNameSetListener) context;
            }
            catch (Exception e){}
        }
    }

    public RadioFragment(){
    };

    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) {

        rootView = inflater.inflate(R.layout.fragment_player, container, false);
        buttonman = (Button)rootView.findViewById(R.id.buttonman);
        buttonman.setOnClickListener(this);
        return rootView;
    }

    @Override
    public void onClick(View v) {
        /*Fragment fragment = new StreamFragment();
        FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.main_container, fragment);
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();*/
        url="www.idontknow.com";
        onNameSetListener.setUrl(url);
        ((MainActivity)a).performStreamClick();
    }

    public interface OnNameSetListener
    {
        public void setUrl(String url);
    }
}

StreamFragment(データを送信したいフラグメント2 -フラグメント1 から)

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class StreamFragment extends Fragment {

    TextView textViewStream;

    public StreamFragment(){};

    @Override
    public View onCreateView(final LayoutInflater inflater,final ViewGroup container,final Bundle savedInstanceState) {
        return  inflater.inflate(R.layout.fragment_stream, container, false);

    }

    public void getUrl(String url)
    {
        textViewStream.setText(url);
    }

}

ログキャット

android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620) 01-06 20:10:24.663 3744-3744/? I/プロセス: シグナルを送信しています。PID: 3744 SIG: 9

4

3 に答える 3

3

frag後で検索するタグを登録することはありません。

MainActivity で次のように変更します。

final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.main_container, fragment, "frag").commit();
...
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, fragment, "frag").commit();
...

それに加えて、StreamFragment クラス内では、レイアウトを拡張した後に TextViewStream 変数を設定することはありません。

@Override
public View onCreateView(final LayoutInflater inflater,final ViewGroup container,final Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_stream, container, false);
    textViewStream = (TextView) view.findViewById(R.id.ID_GOES_HERE);
    return view;
}

編集:さらなるエラー

取得ClassCastExceptionするフラグメントが であるかどうかを確認していないため、 を取得しMainActivity.setUrlていStreamFragmentます。frag3 種類のカスタム フラグメントすべてにタグを登録しているため、失敗するのは理にかなっています。さらなる解決策は次のとおりです。

        fragment = new RadioFragment();
        final FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.main_container, fragment, "radio_fragment").commit();
        ...

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {

            switch (item.getItemId()) {
                String tag = "";
                case R.id.nav_button_one:
                    fragment = new RadioFragment();
                    tag = "radio_fragment";
                    break;
                case R.id.nav_button_two:
                    fragment = new StreamFragment();
                    tag = "stream_fragment";
                    break;
                case R.id.nav_button_three:
                    fragment = new InfoFragment();
                    tag = "info_fragment";
                    break;
            }
            final FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.replace(R.id.main_container, fragment, tag).commit();
            return true;
        }

のタグ文字列を適切に変更しますsetUrl

StreamFragment frag=(StreamFragment) getSupportFragmentManager().findFragmentByTag("stream_fragment");
if (frag != null) frag.getUrl(url);
于 2017-01-06T15:11:12.237 に答える
1

現在の回答は両方とも、クラッシュの問題に関係しています。それがあなたの主な質問に対処することを期待しています。@asadmshah が次の問題を処理したようです。彼の答えに賛成票を投じて、それを受け入れてください。

Google のサンプル コードを使用した場合の警告に関して、新しいフラグメントを作成するように AS に指示した場合に AS が現在表示する内容は次のとおりです。

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnFragmentInteractionListener) {
        mListener = (OnFragmentInteractionListener) context;
    } else {
        throw new RuntimeException(context.toString()
                + " must implement OnFragmentInteractionListener");
    }
}

これのポイントは、アタッチしているアクティビティが、フラグメントで定義したインターフェースを実装していることを確認することです。

インターフェイスに関しては、すべてのフラグメントからアクティビティへの通信はインターフェイスを介して行う必要があります。performStreamClick()インターフェイスを介して呼び出す方法も見つけたほうがよいでしょう。(数か月前に開始したアプリで同じ間違いを犯したことに気づきましたが、今は終了しています:)。

最後に、参考までに、フラグメントの添付されたアクティビティを で取得できますgetActivity()

編集:まず、現在のコードを確認すると役立つ場合があります。多かれ少なかれ、アサドが彼の答えに入れたことをあなたが持っていると仮定します。また、予想される動作は何ですか?で選択してRadioFragmentから に置き換えると思いますStreamFragment。つまり、両方のフラグメントがナビゲーション バー全体を占有し、同時に存在することはありません。これが間違っている場合は、お知らせください。

setUrl()以前と同じ順序でまだ呼び出している場合はperformStreamClick()、その名前でフラグメントを作成したことがないため、null になります。まだ作成していないフラグメントは見つかりません。

これを実際に設定して自分でテストすることなく、URLを のグローバル変数に保存しsetUrl()、クリックリスナーでStreamFragment作成時にそれをに渡す必要があると思います。

それを行うためにサイトに掲載したリンクの「メッセージをフラグメントに配信する」セクションを参照してください

        Bundle args = new Bundle();
        args.putInt(ArticleFragment.ARG_POSITION, position);
        newFragment.setArguments(args);

(明らかに、例の int の代わりに URL 文字列を処理します)

また、すでに存在するはずのフラグメントを検索するときに null を処理することも悪くありません。

    StreamFragment frag=(StreamFragment) getSupportFragmentManager().findFragmentByTag("stream_frag");
    if(frag == null) {
        final FragmentTransaction transaction = fragmentManager.beginTransaction();
        StreamFragment fragment = new StreamFragment();
        transaction.replace(R.id.main_container, fragment, "stream_frag").commit();
    }          
于 2017-01-06T15:45:28.583 に答える
0

フラグメントtextViewStreamで初期化する必要があります。StreamFragment

于 2017-01-06T15:08:05.750 に答える