最初に、これが以前に尋ねられた場合は申し訳ありません。
私のパートナーと私は、Android 用の Firebase リンク アプリを作成しています。Firebase は次のようになります。
+ projects
+ <Some project>
+name: <name>
+users
+<a user>
+<another user>
+ <Another project>
+ users
+ <Some user>
+ <Another user>
問題は、私たちのアプリでは、ユーザーが Firebase にログインし、ユーザーの子で見つかり、その一部であるプロジェクトのみが取り込まれた ListView があることです (つまり、プロジェクトのユーザーには、ログインしているユーザー)。
ログインは正常に機能し、プロジェクトでハードコーディングすると ListView は正常に機能しますが、プロジェクトを見つけると、ListView が作成される前にデータが返されないため、空のリストが表示されます。
これまでのコードは次のとおりです。 これはログイン アクティビティ コードです。
public class LoginActivity extends Activity implements LoaderCallbacks<Cursor> {
/**
* Keep track of the login task to ensure we can cancel it if requested.
*/
// private UserLoginTask mAuthTask = null;
private ProgressDialog mAuthProgressDialog;
/* A reference to the firebase */
private Firebase ref = new Firebase(<URL>);
/* Data from the authenticated user */
private AuthData authData;
/* A tag that is used for logging statements */
private static final String TAG = "LoginDemo";
// UI references.
private AutoCompleteTextView mEmailView;
private EditText mPasswordView;
private View mProgressView;
private View mLoginFormView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Firebase.setAndroidContext(this);
setContentView(R.layout.activity_login);
mAuthProgressDialog = new ProgressDialog(this);
mAuthProgressDialog.setTitle("Loading");
mAuthProgressDialog.setMessage("Authenticating with Firebase...");
mAuthProgressDialog.setCancelable(false);
// Set up the login form.
mEmailView = (AutoCompleteTextView) findViewById(R.id.email);
populateAutoComplete();
mPasswordView = (EditText) findViewById(R.id.password);
mPasswordView
.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int id,
KeyEvent keyEvent) {
if (id == R.id.login || id == EditorInfo.IME_NULL) {
attemptLogin();
return true;
}
return false;
}
});
Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);
mEmailSignInButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
attemptLogin();
}
});
mLoginFormView = findViewById(R.id.login_form);
mProgressView = findViewById(R.id.login_progress);
}
private void populateAutoComplete() {
getLoaderManager().initLoader(0, null, this);
}
/**
* Attempts to sign in or register the account specified by the login form.
* If there are form errors (invalid email, missing fields, etc.), the
* errors are presented and no actual login attempt is made.
*/
public void attemptLogin() {
// if (mAuthTask != null) {
// return;
// }
// Reset errors.
mEmailView.setError(null);
mPasswordView.setError(null);
// Store values at the time of the login attempt.
String email = mEmailView.getText().toString();
String password = mPasswordView.getText().toString();
boolean cancel = false;
View focusView = null;
//Email and Password validity checking
//I.E. does email have an @ and is password longer than 4 characters?
if (cancel) {
// There was an error; don't attempt login and focus the first
// form field with an error.
focusView.requestFocus();
} else {
// Show a progress spinner, and kick off a background task to
// perform the user login attempt.
showProgress(true);
mAuthProgressDialog.show();
loginWithPassword(email, password);
showProgress(false);
}
}
public void openProjectListView(AuthData authdata) {
ArrayList<Project> projects = new ArrayList<Project>();
User user = new User(
<URL>+"users/"
+ authData.getUid());
Map<Project, Role> projectMap = user.getProjects();
for (Project p : projectMap.keySet()) {
projects.add(p);
}
//ArrayAdapter<Project> arrayAdapter = new ArrayAdapter<Project>(this,
// android.R.layout.simple_list_item_activated_1,
// android.R.id.text1, projects);
// setListAdapter(arrayAdapter);
//ListChangeNotifier<Project> lcn = new ListChangeNotifier<Project>(
// arrayAdapter);
//for (Project project : projects) {
// project.setListChangeNotifier(lcn);
//}
mAuthProgressDialog.hide();
Intent intent = new Intent(this, ProjectListActivity.class);
intent.putParcelableArrayListExtra("projects", projects);
this.startActivity(intent);
}
private void setAuthenticatedUser(AuthData authData) {
if (authData != null) {
String name = authData.getUid();
this.authData = authData;
openProjectListView(this.authData);
}
}
public void loginWithPassword(String username, String password) {
ref.authWithPassword(username, password, new AuthResultHandler(
"password"));
}
private class AuthResultHandler implements Firebase.AuthResultHandler {
private final String provider;
public AuthResultHandler(String provider) {
this.provider = provider;
}
@Override
public void onAuthenticated(AuthData authData) {
setAuthenticatedUser(authData);
}
@Override
public void onAuthenticationError(FirebaseError firebaseError) {
showErrorDialog(firebaseError.toString());
}
}
private void showErrorDialog(String message) {
new AlertDialog.Builder(this).setTitle("Error").setMessage(message)
.setPositiveButton(android.R.string.ok, null)
.setIcon(android.R.drawable.ic_dialog_alert).show();
}
これは、プロジェクト リスト アクティビティ コードです。
public class ProjectListActivity extends Activity implements
ProjectListFragment.Callbacks {
public User user;
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
* device.
*/
private boolean mTwoPane;
/**
* The list of projects
*/
private ArrayList<Project> projects;
/**
* A selected Project
*/
private Project projectItem;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.projects = this.getIntent()
.getParcelableArrayListExtra("projects");
boolean tabletSize = (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
if (!tabletSize) {
setContentView(R.layout.activity_project_list);
} else {
setContentView(R.layout.activity_project_twopane);
}
if (findViewById(R.id.project_detail_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-large and
// res/values-sw600dp). If this view is present, then the
// activity should be in two-pane mode.
this.mTwoPane = true;
// In two-pane mode, list items should be given the
// 'activated' state when touched.
((ProjectListFragment) getFragmentManager().findFragmentById(
R.id.project_list)).setActivateOnItemClick(true);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
/**
*
* @return
*/
public ArrayList<Project> getProjects() {
return projects;
}
/**
* Callback method from {@link ProjectListFragment.Callbacks} indicating
* that the item with the given ID was selected.
*/
public void onItemSelected(Project p) {
this.projectItem = p;
if (this.mTwoPane) {
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
Bundle arguments = new Bundle();
// arguments.putString(ProjectDetailFragment.ARG_ITEM_ID, id);
arguments.putParcelable("Project", p);
ProjectDetailFragment fragment = new ProjectDetailFragment();
fragment.setArguments(arguments);
getFragmentManager().beginTransaction()
.replace(R.id.project_detail_container, fragment).commit();
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Intent detailIntent = new Intent(this, ProjectDetailActivity.class);
// detailIntent.putExtra(ProjectDetailFragment.ARG_ITEM_ID, id);
detailIntent.putExtra("Project", p);
startActivity(detailIntent);
}
}
}
最後に、ListChangeNotifier コードを次に示します。
public class ListChangeNotifier<T> {
private ArrayAdapter<T> adapter;
public ListChangeNotifier(ArrayAdapter<T> adapter) {
this.adapter = adapter;
}
/**
*
* The method that will be triggered when data is changed in the object.
*
*/
public void onChange() {
this.adapter.notifyDataSetChanged();
}
}
あまりにも多くのコードを含めて申し訳ありませんが、人々が何を見る必要があるのか わかりません。
助けてくれてありがとう!
編集:
アダプターを扱う Project List Fragment のコードは次のとおりです。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//this.projects = this.getArguments().getParcelableArrayList("Projects");
this.projects = ((ProjectListActivity)this.getActivity()).getProjects();
// Done: replace with a real list adapter.
ArrayAdapter<Project> arrayAdapter = new ArrayAdapter<Project>(getActivity(),
android.R.layout.simple_list_item_activated_1,
android.R.id.text1, this.projects);
setListAdapter(arrayAdapter);
ListChangeNotifier<Project> lcn = new ListChangeNotifier<Project>(arrayAdapter);
for (Project project : this.projects) {
project.setListChangeNotifier(lcn);
}
}