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

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

新規登録して質問してみよう
ただいま回答率
85.47%
Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

Java

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

Android

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Android Studio

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

Q&A

解決済

1回答

1950閲覧

Cloud Firestoreからのデータ取得し、RecyclerViewへの出力したい

Kokeshi432

総合スコア15

Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

Java

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

Android

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Android Studio

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

0グッド

0クリップ

投稿2020/02/04 11:15

編集2020/02/06 09:53

前提・実現したいこと

現在、「位置情報を取得し、そのルートをシェアする」Androidアプリの開発を行なっています。
Cloud Firestoreをデータベースとして用い、位置情報を記録。
その記録した位置情報を参照し、編集するために
参照データをRecyclerViewとしてFragmentに出力しようとした時にうまく作れず詰まってしまいました。

RecyclerViewを生成に用いたFirestoreAdapterはFirestoreチュートリアル内のプログラムでそれを参考にした次第です。
解決方法は勿論、その他おかしなコード等ありましたら何でもご指摘ください。

何卒よろしくお願いいたします。

発生している問題・エラーメッセージ

実行時のエラーとして、Adapterがセットされていないと出ています。

E/RecyclerView: No adapter attached; skipping layout

該当のソースコード

ソースコード全体
https://github.com/takesick/RootShareApp.git

正直、私自身Androidのプログラミング自体が初めてでして、
FirestoreAdapterの部分をはじめ、かなり曖昧な理解で進めているため、至らぬ点が多々あるかと思います。
気になる点ございましたら、合わせてご指摘いただけると今後の勉強のためにも大変ありがたいです。

以下に、主要なファイルの詳細部分を記載します。

FirestoreAdapter.java

(下のLocationsAdapterの継承元)

Java

1public abstract class FirestoreAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> 2 implements EventListener<QuerySnapshot> { 3 4 private static final String TAG = "FirestoreAdapter"; 5 6 private Query mQuery; 7 private ListenerRegistration mRegistration; 8 private ArrayList<DocumentSnapshot> mSnapshots = new ArrayList<>(); 9 10 public FirestoreAdapter(Query query) { 11 mQuery = query; 12 } 13 14 @Override 15 public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) { 16 if (e != null) { 17 Log.w(TAG, "onEvent:error", e); 18 onError(e); 19 return; 20 } 21 22 // Dispatch the event 23 Log.d(TAG, "onEvent:numChanges:" + documentSnapshots.getDocumentChanges().size()); 24 for (DocumentChange change : documentSnapshots.getDocumentChanges()) { 25 switch (change.getType()) { 26 case ADDED: 27 onDocumentAdded(change); 28 break; 29 case MODIFIED: 30 onDocumentModified(change); 31 break; 32 case REMOVED: 33 onDocumentRemoved(change); 34 break; 35 } 36 } 37 onDataChanged(); 38 } 39 40 public void startListening() { 41 if (mQuery != null && mRegistration == null) { 42 mRegistration = mQuery.addSnapshotListener(this); 43 } 44 } 45 46 public void stopListening() { 47 if (mRegistration != null) { 48 mRegistration.remove(); 49 mRegistration = null; 50 } 51 mSnapshots.clear(); 52 notifyDataSetChanged(); 53 } 54 55 public void setQuery(Query query) { 56 // Stop listening 57 stopListening(); 58 59 // Clear existing data 60 mSnapshots.clear(); 61 notifyDataSetChanged(); 62 63 // Listen to new query 64 mQuery = query; 65 startListening(); 66 } 67 68 @Override 69 public int getItemCount() { 70 return mSnapshots.size(); 71 } 72 73 protected DocumentSnapshot getSnapshot(int index) { 74 return mSnapshots.get(index); 75 } 76 77 protected void onDocumentAdded(DocumentChange change) { 78 mSnapshots.add(change.getNewIndex(), change.getDocument()); 79 notifyItemInserted(change.getNewIndex()); 80 } 81 82 protected void onDocumentModified(DocumentChange change) { 83 if (change.getOldIndex() == change.getNewIndex()) { 84 // Item changed but remained in same position 85 mSnapshots.set(change.getOldIndex(), change.getDocument()); 86 notifyItemChanged(change.getOldIndex()); 87 } else { 88 // Item changed and changed position 89 mSnapshots.remove(change.getOldIndex()); 90 mSnapshots.add(change.getNewIndex(), change.getDocument()); 91 notifyItemMoved(change.getOldIndex(), change.getNewIndex()); 92 } 93 } 94 95 protected void onDocumentRemoved(DocumentChange change) { 96 mSnapshots.remove(change.getOldIndex()); 97 notifyItemRemoved(change.getOldIndex()); 98 } 99 100 protected void onError(FirebaseFirestoreException e) { 101 Log.w(TAG, "onError", e); 102 }; 103 104 protected void onDataChanged() {} 105}

LocationsAdapter.java

(FirestoreAdapterを継承したRecyclerViewに実装するAdapter)

Java

1 2public class LocationsAdapter extends FirestoreAdapter<LocationsAdapter.ViewHolder> { 3 4 public interface OnLocationsSelectedListener { 5 void onLocationsSelected(DocumentSnapshot locationData); 6 } 7 8 private OnLocationsSelectedListener mListener; 9 10 public LocationsAdapter(Query query, OnLocationsSelectedListener listener) { 11 super(query); 12 mListener = listener; 13 } 14 15 @Override 16 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 17 LayoutInflater inflater = LayoutInflater.from(parent.getContext()); 18 return new ViewHolder(inflater.inflate(R.layout.list_location, parent, false)); 19 } 20 21 @Override 22 public void onBindViewHolder(ViewHolder holder, int position) { 23 holder.bind(getSnapshot(position), mListener); 24 } 25 26 static class ViewHolder extends RecyclerView.ViewHolder { 27 28 TextView timeView; 29 TextView accuracyView; 30 TextView latitudeView; 31 TextView longitudeView; 32 33 public ViewHolder(View itemView) { 34 super(itemView); 35 timeView = itemView.findViewById(R.id.created_at); 36 accuracyView = itemView.findViewById(R.id.accuracy); 37 latitudeView = itemView.findViewById(R.id.lat); 38 longitudeView = itemView.findViewById(R.id.lng); 39 } 40 41 public void bind(final DocumentSnapshot snapshot, 42 final OnLocationsSelectedListener listener) { 43 44 LocationData locationData = snapshot.toObject(LocationData.class); 45 46 timeView.setText("計測日時:" + String.format("%.5f", locationData.getCreated_at())); 47 accuracyView.setText("|精度:" + String.format("%.5f", locationData.getAccuracy())); 48 latitudeView.setText("|緯度:"+ String.format("%.5f", locationData.getLatitude())); 49 longitudeView.setText("|経度:"+ String.format("%.5f", locationData.getLongitude())); 50 51 // Click listener 52 itemView.setOnClickListener(new View.OnClickListener() { 53 @Override 54 public void onClick(View view) { 55 if (listener != null) { 56 listener.onLocationsSelected(snapshot); 57 } 58 } 59 }); 60 } 61 } 62}

RootsFragment.java

(RecyclerViewを設置しているFragment)
要素のクリック後の画面が用意できていないため、コメントアウトしている部分があります。

Java

1 2public class RootsFragment extends Fragment implements LocationsAdapter.OnLocationsSelectedListener { 3 4 private RecyclerView mRecyclerView; 5 private LocationsAdapter mAdapter; 6 private FirebaseFirestore mFirestore; 7 private Query mQuery; 8 private int LIMIT = 10; 9 10 @Override 11 public View onCreateView(@NonNull LayoutInflater inflater, 12 ViewGroup container, 13 Bundle savedInstanceState) { 14 15 View view = inflater.inflate(R.layout.roots_frag, container, false); 16 mRecyclerView = view.findViewById(R.id.LocationList);; 17 18 mFirestore = FirebaseFirestore.getInstance(); 19 mQuery = mFirestore.collection("locations") 20 .orderBy("created_at") 21 .limit(LIMIT); 22 23 mAdapter = new LocationsAdapter(mQuery, this) { 24 @Override 25 protected void onDataChanged() { 26 // Show/hide content if the query returns empty. 27 if (getItemCount() == 0) { 28 mRecyclerView.setVisibility(View.GONE); 29 } else { 30 mRecyclerView.setVisibility(View.VISIBLE); 31 } 32 } 33 34 @Override 35 protected void onError(FirebaseFirestoreException e) { 36 // Show a snackbar on errors 37// Snackbar.make(findViewById(android.R.id.content), 38// "Error: check logs for info.", Snackbar.LENGTH_LONG).show(); 39 } 40 }; 41 42// mAdapterをmRecyclerViewにセットする 43 mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); 44 mRecyclerView.setAdapter(mAdapter); 45 46 Log.e("mAdapter", String.valueOf(mAdapter)); 47 return view; 48 } 49 50 @Override 51 public void onStart() { 52 super.onStart(); 53 54 // Start listening for Firestore updates 55 if (mAdapter != null) { 56 mAdapter.startListening(); 57 } 58 } 59 60 61 @Override 62 public void onLocationsSelected(DocumentSnapshot locationData) { 63// Intent intent = new Intent(this, LocationDetailActivity.class); 64// intent.putExtra(LocatonDetailActivity.KEY_RESTAURANT_ID, locationData.getId()); 65// 66// startActivity(intent); 67// overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_to_left); 68 } 69}

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

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

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

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

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

kakajika

2020/02/14 23:44

どううまく動いていないのかわからないので、詳しい内容を追記してください。
guest

回答1

0

ベストアンサー

fragment内でsetAdapter()onCreateView()内で行うのではなくonViewCreated()内で行う必要があります。(おそらくsetAdapterメソッドにはリストの描画処理も含んでいるので、RecyclerViewが生成される前にsetAdapterすると何も起こりません)
以下のようにすると動作すると思います。(私はJavaではなくKotlinで開発しているので細かい部分が合っているか分かりませんが)

Java

1public class RootsFragment extends Fragment implements LocationsAdapter.OnLocationsSelectedListener { 2 3 private RecyclerView mRecyclerView; 4 private LocationsAdapter mAdapter; 5 private FirebaseFirestore mFirestore; 6 private Query mQuery; 7 private int LIMIT = 10; 8 9 @Override 10 public View onCreateView(@NonNull LayoutInflater inflater, 11 ViewGroup container, 12 Bundle savedInstanceState) { 13 14 View view = inflater.inflate(R.layout.roots_frag, container, false); 15 mRecyclerView = view.findViewById(R.id.LocationList);; 16 17 mFirestore = FirebaseFirestore.getInstance(); 18 mQuery = mFirestore.collection("locations") 19 .orderBy("created_at") 20 .limit(LIMIT); 21 22 mAdapter = new LocationsAdapter(mQuery, this) { 23 @Override 24 protected void onDataChanged() { 25 // Show/hide content if the query returns empty. 26 if (getItemCount() == 0) { 27 mRecyclerView.setVisibility(View.GONE); 28 } else { 29 mRecyclerView.setVisibility(View.VISIBLE); 30 } 31 } 32 33 @Override 34 protected void onError(FirebaseFirestoreException e) { 35 // Show a snackbar on errors 36// Snackbar.make(findViewById(android.R.id.content), 37// "Error: check logs for info.", Snackbar.LENGTH_LONG).show(); 38 } 39 }; 40 41 mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); 42 Log.e("mAdapter", String.valueOf(mAdapter)); 43 return view; 44 } 45 46 @Override 47 public void onStart() { 48 super.onStart(); 49 50 // Start listening for Firestore updates 51 if (mAdapter != null) { 52 mAdapter.startListening(); 53 } 54 } 55 56// 追加 57 @Override 58 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 59 //mAdapterをmRecyclerViewにセットする 60 mRecyclerView.setAdapter(mAdapter); 61 } 62 63 @Override 64 public void onLocationsSelected(DocumentSnapshot locationData) { 65// Intent intent = new Intent(this, LocationDetailActivity.class); 66// intent.putExtra(LocatonDetailActivity.KEY_RESTAURANT_ID, locationData.getId()); 67// 68// startActivity(intent); 69// overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_to_left); 70 } 71}

投稿2020/02/13 12:51

編集2020/02/13 12:52
chika3742

総合スコア113

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

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

kakajika

2020/02/14 23:33

> fragment内でsetAdapter()をonCreateView()内で行うのではなくonViewCreated()内で行う必要があります。(おそらくsetAdapterメソッドにはリストの描画処理も含んでいるので、RecyclerViewが生成される前にsetAdapterすると何も起こりません) そのようなことは無いと思います。Viewのinflate以外の処理はonViewCreated内で行うことが推奨されてはいますが、onCreateView内に書いたとしても同じように動作するはずです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問