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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

1636閲覧

androidStudio 画面遷移で前の画面や後ろ画面のメッソドにアクセスするには

tunechan

総合スコア16

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2020/04/16 07:53

androidstudio(Ver3.6.1 Java) を使って,プログラムを作っています。androidは初心者です。iOS(swift)は、多少経験があります。

ナビゲーションエディターを使って、下図のような3枚の画面遷移プログラムを作りました。

イメージ説明

やりたいことは、二つあります。

1)3枚目Third画面(ThirdFragment)上の「SECOND_FUNCTION」ボタンアクションで、SecondFragment(Second画面)内のメソッドを動 かしたいのです。しかし、findFragmentByID(R.id.seconddFragment)で、Second画面のfragmentを取得しようとすると下図のようにnullが返ってきます。当然クラッシュします。どのようにすればsecond画面のfragmentを取得し、メッソドにアクセスできるのかご教授願います。

イメージ説明説明](a0b67e3bc3f7fe842e2c7d365719863b.jpeg)

iOS(xcode:swift)では、
let vc:SecondViewController = navigationController?.viewControllers[(navigationController?.viewController.count)! -2]
as! SecondViewController
のような感じで、前の画面のインスタンスが取得できました。

androidstudioの画面とコードを下に示します。


イメージ説明
MainActivity

package com.example.test_navigation;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.navigation.Navigation;
Import androidx.navigation.ui.NavigationUI;
Import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NavigationUI.setupWithNavController((Toolbar)findViewById(R.id.toolbar),
Navigation.findNavController(this, R.id.fragment));
}
}

FirstFragment
package com.example.test_navigation;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class FirstFragment extends Fragment {
public FirstFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

View view = inflater.inflate(R.layout.fragment_first, container, false); view.findViewById(R.id.btnFirstTopNext).setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { Navigation.findNavController(v).navigate(R.id.secondFragment); } } ); return view; }

}

SecondFragment
package com.example.test_navigation;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class SecondFragment extends Fragment {
public SecondFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_second, container, false);
view.findViewById(R.id.btnSecondToNext).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
Navigation.findNavController(v).navigate(R.id.thirdFragment);
}
}
);
return view;
}

public void secondFun(){ Log.d("in A2", "called FromA3");  // **__ここにアクセスしたい!!__** }

}

ThirdFragment
package com.example.test_navigation;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.navigation.Navigation;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.Objects;
public class ThirdFragment extends Fragment {
public ThirdFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_third, container, false);
view.findViewById(R.id.btnThirdToTop).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
Navigation.findNavController(v).navigate(R.id.action_global_go_Top); // Global Action
}
}
);
view.findViewById(R.id.btnSecondFunOn).setOnClickListener(
new View.OnClickListener() {
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onClick(View v) {
FragmentManager Fragmentmana = Objects.requireNonNull(getFragmentManager());
SecondFragment fragment = (SecondFragment) Fragmentmana.findFragmentById(R.id.secondFragment);
fragment.secondFun(); // ここからアクセスしたい!!
}
}
);
return view;
}
}

Navigation
nav.xml

<?xml version="1.0" encoding="utf-8"?>

<navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav" app:startDestination="@id/firstFragment">
<!-- Global Action -->
<action android:id="@+id/action_global_go_Top" app:destination="@id/firstFragment" app:popUpTo="@id/nav" app:popUpToInclusive="true"/>
<!-- Global Action ここまで -->
<fragment android:id="@+id/firstFragment" android:name="com.example.test_navigation.FirstFragment" android:label="Firstページ" tools:layout="@layout/fragment_first">
<action android:id="@+id/action_firstFragment_to_secondFragment" app:destination="@id/secondFragment" />
</fragment>
<fragment android:id="@+id/secondFragment" android:name="com.example.test_navigation.SecondFragment" android:label="Secondページ" tools:layout="@layout/fragment_second">
<action android:id="@+id/action_secondFragment_to_thirdFragment2" app:destination="@id/thirdFragment" />
</fragment>
<fragment android:id="@+id/thirdFragment" android:name="com.example.test_navigation.ThirdFragment" android:label="Thirdページ" tools:layout="@layout/fragment_third" />
</navigation>

2)二つ目です。SecondFragmentにBLEの通信プログラムを置きたいと考えております。ThirdFragmentからSecondFragment内に置いた通信メッソド(これが上のsecondFun()メソッド)を動かし、通信済みバイト数をThird画面に随時表示させたいと考えております。
iOSでは、notificationCenter.postで通知し、thirdFragmentで拾っておりました。androidでも同様の機能はありますか。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

構造的に, 並列なフラグメント間で操作しあうのは良くありません.
フラグメントは普通(?)の View と同じく表示の為に使用し, 必要なデータや(画面に直接因らない)処理は Activity (出来れば MVVM における Model ) で行うという形がより良いものと思います.

ですので, Third から Second のメソッドを呼ぶという点におきましては, Second 画面の該当メソッドを Activity(もしくは Model)に移動して呼び出すようにすること, Second に BLE の通信プログラムを置きたいという点に置きましても, Activity (もしくは Model)に通信プログラムを置くことが良いものと思います.
Activity(もしくは Model)での動作から各フラグメントが表示する部分に関しましては, ViewModel/LiveData 等のクラスがありますので, お調べになっては如何でしょうか.

投稿2020/04/16 11:18

jimbe

総合スコア12646

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tunechan

2020/04/17 14:10

jimbe様 ありがとうございます。 >構造的に, 並列なフラグメント間で操作しあうのは良くありません. Activity に置いたメッソドはアクセスできるのは確認しました。そこから配下のFragment上にある部品やメソッドもアクセスできるようになりました。 感謝です。しかし、ナビゲーションエディターで配置したFragment同士でやり取りする方法はないものでしょうか?
jimbe

2020/04/17 18:47 編集

Fragment の普通(?) の View との違いは, Activity 同様ライフサイクルを持ち, OS によって(アプリの知らぬ間に)削除・再生成される可能性があるということです. もちろん無作為に削除されたりするわけでは無く, OS 側の理由やタイミングがあるわけですが, アプリがそれに抵抗したりは出来ません. 従いまして, 例えばボタンとクリックリスナーのように, 呼ぶ側のフラグメントが呼ばれる側のフラグメントの参照を持っておいて必要になったら呼ぶということが出来ません. (どちらか, もしくは両方が削除・再生成されると, 古い参照は無効になります.) 参照として確実なのは Fragment を持つ親, つまり Activity ですので, 結局 Activity 経由でやりとりする形になります.
tunechan

2020/04/20 01:16

jimbe様 ありがとうございます。 自分なりにいろいろと試して見ました。最初の質問のように画面が遷移していく形でなく、一つの画面上(activity_main.xml)に、二つの.xmlファイル(Fragment)を配置し、Fragment間でやり取りし合うようにすれば、どちらのFragmentも存在したままで、OSに意図せず削除されることはないのではと考えて実験してみましたが上手くいきませんでした。 すなわち、画面を遷移させる場合と同じく、Fragment2から FragmentManager fragmentmanager = getFragmentMnager(); Fragment1 fragment1 = (Fragment1)fragmentmanager.findFragmentById(R.id.Fragment1_Id): として、相手のFragment1を取得しようとしても、nullが返ってくるようです。合点がいきませんが Fragent間の操作は、Activity_mainを通すことにします。 ありがとうございました。
tunechan

2020/04/20 23:55

訂正です。 昨日のコメントで、一つの画面で二つのフラグメントを配置した場合も上手くいかないと述べましたが、 プログラムにミスがあり訂正した結果、上手くいきました。 ひとつ気が付いた点ですが、ナビゲーションエディターを使って全画面遷移させ上手くいかない場合は、 getFragmentMnager()に取り消し線が出てdeprecation になっていますが、同一画面で二つのフラグメント を配置した場合にはそうはなっていません。android studioのバージョンやimport文などの条件は同じです。 ありがとうございました。
jimbe

2020/04/21 12:18 編集

表示中のフラグメントは当然存在しますので, 使用することは出来るかと思います. FragmentManager はパッケージの違う版が幾つかあり, 意識せずにクラス名だけを見ていると混在してしまって妙なコトになる場合があります. (FragmentManager 以外でもありますが.) その辺り, どのライブラリのパッケージのメソッドがどの版を返すのか等をドキュメントで確認されると宜しいかと思います.
tunechan

2020/04/21 08:18

jimbe様 ありがとうございます。 確かに同じgetFragmentManger でも、「Go To」「Declaration or Usages」で定義を見に行くと 違うもののようです。getFragmentManagerの部分を消して、再度タイプしようとしても選択候補メッソドは同じです。ナビゲーションエディターを使った方は、それ用のライブラリーがimportされており、それが原因のように思われます。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問