FireBase实时数据库花费太多时间来检索“ ListView”数据

时间:2018-09-26 08:15:40

标签: java android firebase firebase-realtime-database

MainActivity(以及其他活动中,为简单起见,我们将重点放在此)上,我从FireBase实时数据库中检索了一些项目,我们所讨论的是2-3个适合ListView。加载信息通常需要2-3秒,这似乎很奇怪。

此外,加载图标在此期间未显示,这让我感到困惑。

我正在按照FireBase指示的常规方式检索数据,所以我想知道是什么原因造成的。

编辑-尝试Alex Mamo的建议, 这是Logcat:

FATAL EXCEPTION: main
Process: com.example.guyerez.todotiger, PID: 23964
android.content.res.Resources$NotFoundException: String resource ID #0x0
    at android.content.res.Resources.getText(Resources.java:347)
    at android.content.res.MiuiResources.getText(MiuiResources.java:97)
    at android.widget.TextView.setText(TextView.java:4557)
    at com.example.guyerez.todotiger.MainActivity$TaskListHolder.setTaskList(MainActivity.java:464)
    at com.example.guyerez.todotiger.MainActivity$1.onBindViewHolder(MainActivity.java:101)
    at com.example.guyerez.todotiger.MainActivity$1.onBindViewHolder(MainActivity.java:98)
    at com.firebase.ui.database.FirebaseRecyclerAdapter.onBindViewHolder(FirebaseRecyclerAdapter.java:122)
    at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
    at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
    at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
    at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
    at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
    at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557)
    at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
    at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
    at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
    at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3641)
    at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:4194)
    at android.view.View.layout(View.java:17548)
    at android.view.ViewGroup.layout(ViewGroup.java:5614)
    at android.support.constraint.ConstraintLayout.onLayout(ConstraintLayout.java:1915)
    at android.view.View.layout(View.java:17548)
    at android.view.ViewGroup.layout(ViewGroup.java:5614)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
    at android.view.View.layout(View.java:17548)
    at android.view.ViewGroup.layout(ViewGroup.java:5614)
    at android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:444)
    at android.view.View.layout(View.java:17548)
    at android.view.ViewGroup.layout(ViewGroup.java:5614)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
    at android.view.View.layout(View.java:17548)
    at android.view.ViewGroup.layout(ViewGroup.java:5614)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
    at android.view.View.layout(View.java:17548)
    at android.view.ViewGroup.layout(ViewGroup.java:5614)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
    at com.android.internal.policy.DecorView.onLayout(DecorView.java:727)
    at android.view.View.layout(View.java:17548)
    at android.view.ViewGroup.layout(ViewGroup.java:5614)
    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2384)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2111)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1288)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6359)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:873)
    at android.view.Choreographer.doCallbacks(Choreographer.java:685)
    at android.view.Choreographer.doFrame(Choreographer.java:621)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:859)
    at android.os.Handler.handleCallback(Handler.java:754)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:163)
    at android.app.ActivityThread.main(ActivityThread.java:6237)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:877)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

这是我的新MainActivity代码

public class MainActivity extends AppCompatActivity {

private static final String CHANNEL_ID = "123";
final Context context = this;
public static final int SIGN_IN = 1;
public static String currentTaskListId;
public static String currentUserId;
private TaskListAdapter mTaskListAdapter;
//TextView that is displayed when the list is empty//
private TextView mEmptyStateTextView;
//The loading indicator //
private View loadingIndicator;


// Firebase instance variables

private FirebaseAuth mFirebaseAuth;
private FirebaseAuth.AuthStateListener mAuthStateListener;
private FirebaseDatabase mFirebaseDatabase;
private DatabaseReference mTaskListDatabaseReference;
private ChildEventListener mChildEventListener;
private FirebaseRecyclerAdapter<TaskList, TaskListHolder> firebaseRecyclerAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Set the content of the activity to use the activity_main.xml layout file - the task lists
    setContentView(R.layout.activity_main);


    //Create the notification channel
    createNotificationChannel();

    RecyclerView recyclerView = findViewById(R.id.recycler_view);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
    Query query = rootRef.child("users");
    // Initialize Firebase components
    mFirebaseAuth = FirebaseAuth.getInstance();
    mFirebaseDatabase = FirebaseDatabase.getInstance();

    FirebaseRecyclerOptions<TaskList> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<TaskList>()
            .setQuery(query, TaskList.class)
            .build();

    firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<TaskList, TaskListHolder>(firebaseRecyclerOptions) {
        @Override
        protected void onBindViewHolder(@NonNull TaskListHolder taskListHolder, int position, @NonNull TaskList blogPost) {
            taskListHolder.setTaskList(blogPost);
        }

        @Override
        public TaskListHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.tlist_item, parent, false);

            return new TaskListHolder(view);
        }
    };
    recyclerView.setAdapter(firebaseRecyclerAdapter);


    //Initialize firebase authentication
    mAuthStateListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
            FirebaseUser user = firebaseAuth.getCurrentUser();
            if (user != null) {
                // user is signed in
                currentUserId=user.getUid();
                onSignedInInitialize(user.getUid());

            } else {
                // user is signed out
                onSignedOutCleanup();
                startActivityForResult(
                        AuthUI.getInstance()
                                .createSignInIntentBuilder()
                                .setIsSmartLockEnabled(false)
                                .setAvailableProviders(Arrays.asList(
                                        new AuthUI.IdpConfig.EmailBuilder().build(),
                                        new AuthUI.IdpConfig.GoogleBuilder().build()))
                                .setTosAndPrivacyPolicyUrls("https://superapp.example.com/terms-of-service.html",
                                        "https://superapp.example.com/privacy-policy.html")
                                .build(),
                        SIGN_IN);
            }
        }
    };

    //Set and create the FAB and it's action listener
    FloatingActionButton fab = findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // Get add_list.xml view
            LayoutInflater li = LayoutInflater.from(context);
            View addTaskListView = li.inflate(R.layout.add_list, null);

            //Create the prompt to enable the user to create a new task list
            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                    context);

            // Set add_list.xml as the layout for alertdialog builder
            alertDialogBuilder.setView(addTaskListView);

            //Set the user input box
            final EditText userInput = (EditText) addTaskListView
                    .findViewById(R.id.edit_list_name);



            // Set dialog message
            alertDialogBuilder
                    .setCancelable(false)
                    .setPositiveButton("Create",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog,int id) {
                                    // Get list title from user and create a new task list
                                    //Also fetch the FireBase ID and connect it to the new task list.
                                    String mTaskListId = mTaskListDatabaseReference.push().getKey();
                                    TaskList taskList = new TaskList(userInput.getText().toString(),mTaskListId,0);
                                    mTaskListDatabaseReference.child(mTaskListId).setValue(taskList);
                                }
                            })
                    .setNegativeButton("Cancel",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog,int id) {
                                    dialog.cancel();
                                }
                            });

            // Create the dialog
            final AlertDialog alertDialog = alertDialogBuilder.create();

            // Enable create button when input is not empty
            userInput.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                }

                @Override
                public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                    if (charSequence.toString().trim().length() > 0) {
                        alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
                    } else {
                        alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
                    }
                }

                @Override
                public void afterTextChanged(Editable editable) {
                }
            });

            // Show the dialog
            alertDialog.show();
            alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
        }
    });

}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == SIGN_IN) {
        if (resultCode == RESULT_OK) {
            // Sign-in succeeded, set up the UI
            Toast.makeText(this, "Signed in!", Toast.LENGTH_SHORT).show();
        } else if (resultCode == RESULT_CANCELED) {
            // Sign in was canceled by the user, finish the activity
            Toast.makeText(this, "Sign in canceled", Toast.LENGTH_SHORT).show();
            finish();
        }
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.mini_menu,menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.sign_out:
            AuthUI.getInstance().signOut(this);
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }

}

@Override
protected void onResume() {
    super.onResume();
    mFirebaseAuth.addAuthStateListener(mAuthStateListener);

    }

@Override
protected void onPause() {
    super.onPause();
    if (mAuthStateListener != null) {
        mFirebaseAuth.removeAuthStateListener(mAuthStateListener);
    }
    mTaskListAdapter.clear();
   // detachDatabaseReadListener();

}

private void onSignedInInitialize(final String userId) {

    //Get reference for the task list for the logged in user and attach the database listener
    mTaskListDatabaseReference=mFirebaseDatabase.getReference().child("users").child(userId);
 //   attachDatabaseReadListener();

}

private void onSignedOutCleanup() {
  //  mTaskListAdapter.clear();
 //   detachDatabaseReadListener();
}
private void attachDatabaseReadListener() {
    if (mChildEventListener == null) {
        mChildEventListener = new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                mEmptyStateTextView.setVisibility(View.GONE);
                loadingIndicator.setVisibility(View.GONE);
                TaskList taskList = dataSnapshot.getValue(TaskList.class);
                mTaskListAdapter.add(taskList);
            }
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
            public void onChildRemoved(DataSnapshot dataSnapshot) {
                if(mTaskListAdapter.isEmpty()){
                    mEmptyStateTextView.setVisibility(View.VISIBLE);
                    mEmptyStateTextView.setText("No task lists, add a new one!");
                }
            }
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
            public void onCancelled(DatabaseError databaseError) {}
        };

    }
    mTaskListDatabaseReference.addChildEventListener(mChildEventListener);

}
private void detachDatabaseReadListener() {
    if (mChildEventListener != null) {
        mTaskListDatabaseReference.removeEventListener(mChildEventListener);
        mChildEventListener = null;
    }
}

public static String getCurrentTaskListId() {
    return currentTaskListId;
}
public static String getCurrentUserId() {
    return currentUserId;
}

/**
 * MENU
 */

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo){
    if (v.getId() == R.id.task_list_view){
        AdapterView.AdapterContextMenuInfo info =(AdapterView.AdapterContextMenuInfo)menuInfo;
        menu.add(0,0,0,"Delete");
        menu.add(0,1,1,"TEST");
    }
}

@Override
public boolean onContextItemSelected(MenuItem menuItem){
    AdapterView.AdapterContextMenuInfo info=(AdapterView.AdapterContextMenuInfo)menuItem.getMenuInfo();
    TaskList taskListClicked=mTaskListAdapter.getItem(info.position);
    Log.d("check","" +taskListClicked.getTitle());
    switch (menuItem.getItemId()) {
        case 0:
            mTaskListDatabaseReference.child(taskListClicked.getId()).removeValue();
            mTaskListAdapter.remove(taskListClicked);
            Toast.makeText(this, "Task List deleted!", Toast.LENGTH_LONG).show();
            break;

        case 1:
            // Create an explicit intent for an Activity in your app
            Intent intent = new Intent(this, TaskActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
                    .setSmallIcon(R.drawable.fui_ic_mail_white_24dp)
                    .setContentTitle("My notification")
                    .setContentText("Hello World!")
                    .setPriority(NotificationCompat.PRIORITY_HIGH)
                    // Set the intent that will fire when the user taps the notification
                    .setContentIntent(pendingIntent)
                    .setAutoCancel(true);


            //get the current task list's ID
            currentTaskListId=taskListClicked.getId();
            NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);

            // notificationId is a unique int for each notification that you must define
            notificationManager.notify(0, mBuilder.build());

        default:
            break;

    }
    return true;
}

private void createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is new and not in the support library
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        CharSequence name = getString(R.string.channel_name);
        String description = getString(R.string.channel_description);
        int importance = NotificationManager.IMPORTANCE_HIGH;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
        channel.setDescription(description);
        // Register the channel with the system; you can't change the importance
        // or other notification behaviors after this
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

private class TaskListHolder extends RecyclerView.ViewHolder {
    private TextView titleTextView, taskNumTextView;

    TaskListHolder(View itemView) {
        super(itemView);
        titleTextView = itemView.findViewById(R.id.list_title);
        taskNumTextView = itemView.findViewById(R.id.num_of_tasks);
    }

    void setTaskList(TaskList taskList) {
        String title = taskList.getTitle();
        titleTextView.setText(title);
        int taskNum = taskList.getTaskNum();
        taskNumTextView.setText(taskNum);
    }
}

@Override
protected void onStart() {
    super.onStart();
    firebaseRecyclerAdapter.startListening();
}

@Override
protected void onStop() {
    super.onStop();

    if (firebaseRecyclerAdapter!= null) {
        firebaseRecyclerAdapter.stopListening();
    }
}

}

1 个答案:

答案 0 :(得分:1)

要解决此问题,请更改以下代码行:

taskNumTextView.setText(taskNum);

taskNumTextView.setText(String.valueOf(taskNum));

您传递给setText()方法的参数应该是String类型,而不是int