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

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

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

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Java

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

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

1回答

709閲覧

Fragment間のデータの受け渡しで失敗(Android/Java)

Yakusugi

総合スコア123

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Java

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

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2022/10/03 05:23

JavaでAndroidの家計簿アプリを作成しています。

現在、Fragment間のデータの受け渡しで問題が起きています。

目的としては、
Fragment1からFragment2へデータを渡し、
Fragment2で渡されたデータの編集を行い、
Fragment1に戻し、問題無くFragment1のListViewでもデータの閲覧が出来、
戻ったFragment1のListViewの同じアイテムか別のアイテムを選択しても、
問題無く続けて編集(Fragment1からFragment2へデータを渡す)が出来るようにすることです。

上記説明に当てはめると、
SearchFragment.javaがFragment1(データ閲覧画面で、ListView上のアイテムをクリックするとAddSpendingFragmentへ画面遷移)、
AddSpendingFragmentがFragment2(受け取ったデータを編集し、SearchFragmentに戻す画面)
となります。

問題なのは、AddSpendingFragmentの方で、
fragmentManager.popBackStack();で呼び出し元のSearchFragmentに画面遷移しますが、
SearchFragmentで改めて検索を行い、ListView上のアイテムをクリックすると、アプリが落ちてしまいます。

下記がエラー表示となります。

java.lang.NullPointerException: Attempt to invoke interface method 'androidx.lifecycle.Lifecycle androidx.lifecycle.LifecycleOwner.getLifecycle()' on a null object reference at androidx.lifecycle.LiveData.observe(LiveData.java:192) at com.myproject.offlinebudgettrackerappproject.AddSpendingFragment$4.onFragmentResult(AddSpendingFragment.java:229) at androidx.fragment.app.FragmentManager$LifecycleAwareResultListener.onFragmentResult(FragmentManager.java:249) at androidx.fragment.app.FragmentManager.setFragmentResult(FragmentManager.java:916) at com.myproject.offlinebudgettrackerappproject.SearchFragment$4.onItemClick(SearchFragment.java:208) at android.widget.AdapterView.performItemClick(AdapterView.java:330) at android.widget.AbsListView.performItemClick(AbsListView.java:1190) at android.widget.AbsListView$PerformClick.run(AbsListView.java:3198) at android.widget.AbsListView$3.run(AbsListView.java:4116) at android.os.Handler.handleCallback(Handler.java:883) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7356) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

具体的なアプリの動きに関しては、YouTube動画として公開していますので、ご確認頂ければ幸いです。
https://youtube.com/shorts/dutsY6umTLU?feature=share

下記コードでは、SearchFragmentでFragmentManagerを使ってfragment間でのデータの受け渡しを行っています。 

SearchFragment

searchListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { String date = adapterView.getItemAtPosition(position).toString(); List<BudgetTrackerSpending> budgetSpendingListItems = searchStoreNameLists; int intId = (int) id; BudgetTrackerSpending storeItemId = budgetSpendingListItems.get(intId); //fragment intent Fragment fragment = new AddSpendingFragment(); Bundle result = new Bundle(); result.putInt("storeId", storeItemId.getId()); fragment.setArguments(result); FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); fragmentManager.setFragmentResult("shop_search_id", result); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.main_container, fragment); fragmentTransaction.addToBackStack(null); fragmentTransaction.commit(); } });

※下記コメントアウトしている箇所は、今後実装予定箇所となるため、一時的にコメントアウトしています。
AddSpendingFragment

updateButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (searchShopId != 0) { // idStore = shopFragmentIntentId; // idProduct = productFragmentIntentId; // idDate = dateFragmentIntentId; // idReplace = replacedActivityIntentId; String date = enterDate.getText().toString(); String storeName = enterStoreName.getText().toString(); String productName = enterProductName.getText().toString(); String productType = enterProductType.getText().toString(); double price = Double.parseDouble(enterPrice.getText().toString()); if (enterVatRate.getText().toString().trim().length() > 0) { Log.d("09120222", "onClick: " + enterVatRate.getText().toString()); // enterVatRate.setText(String.valueOf(0.0)); enterVatRate.setText(null); } else { vatRate = Double.parseDouble(enterVatRate.getText().toString()); } String notes = enterNotes.getText().toString(); if (TextUtils.isEmpty(date) || TextUtils.isEmpty(storeName) || TextUtils.isEmpty(productName) || TextUtils.isEmpty(productType) || TextUtils.isEmpty(String.valueOf(price)) || TextUtils.isEmpty(String.valueOf(vatRate)) || TextUtils.isEmpty(notes)) { Snackbar.make(enterProductName, R.string.empty, Snackbar.LENGTH_SHORT).show(); } else { BudgetTrackerSpending budgetTrackerSpending = new BudgetTrackerSpending(); if (searchShopId != 0) { budgetTrackerSpending.setId(searchShopId); } // } else if (productFragmentIntentId != 0) { // budgetTracker.setId(idProduct); // } else if (dateFragmentIntentId != 0) { // budgetTracker.setId(idDate); // } else if (replacedActivityIntentId != 0) { // budgetTracker.setId(idReplace); // } budgetTrackerSpending.setDate(date); budgetTrackerSpending.setStoreName(storeName); budgetTrackerSpending.setProductName(productName); budgetTrackerSpending.setProductType(productType); budgetTrackerSpending.setPrice(price); budgetTrackerSpending.setTaxRate(vatRate); budgetTrackerSpending.setNotes(notes); BudgetTrackerSpendingViewModel.updateBudgetTrackerSpending(budgetTrackerSpending); // Todo Automatic search after updated an item // if (searchShopId != 0) { // setResult(RESULT_OK, shopFragmentGetIntent); // } else if (productFragmentIntentId != 0) { // setResult(RESULT_OK, productFragmentGetIntent); // } FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); fragmentManager.popBackStack(); } } } });

お手数ですが、解決の為、アドバイスがあればご教示頂けますと幸いです。

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

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

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

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

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

jimbe

2022/10/03 10:07 編集

コードを見た限りでまだ動画も見ていませんが、基本的な事として、フラグメント間の遷移はそのフラグメントが乗るアクティビティに(メソッドを作る等で)任せた方が良いと思います。 フラグメントは自分のやるべきことを行うのみで、ボタンが押された時に行うことが自分の担当で無ければアクティビティに押されたことを通知するという形にすることで、例えばスマホではフラグメントを切り替えるがタブレットでは両方とも表示されているという形にも対応できます。 (popBackStack はスマホの基本機能である「戻る」ボタンに相当するもので、基本的にはアプリ内で機能的に用いるものでは無いと認識しています。)
Yakusugi

2022/10/04 23:24

返信遅れました。 いつもアドバイス頂きありがとうございます。 確かに今回データの受け渡しを行うFragmentは乗っかっているActivityが別であるため、色々と制約がありました。 確かに、乗っかっているActivityに任せた方が効率的ですね。 その線で調べてみます。
jimbe

2022/10/05 02:45

Add のフラグメントの popBackStack() は言わば自殺ですので、それがアクティビティ等に移れば何か変わるのではと期待しています。
guest

回答1

0

自己解決

newInstanceを使うことでMainActivityからfragmentを呼び出す事が出来ました。

投稿2022/11/18 01:07

Yakusugi

総合スコア123

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問