我對android非常陌生,這是我的第二個應用程序。我正在製作一個標籤式活動,其中第一個片段具有用於創建新任務的表單,第二個片段具有所有保存的任務的列表,第三個片段將在第二個列表中從列表中選擇時顯示任務上的評論分段。當我點擊第一個片段上的保存任務按鈕時,應用程序會正確保存該任務,並將其顯示在下一個片段中的任務列表中。但是,我不想在第一個片段中使用「保存任務」按鈕。我希望能夠在用戶從第一個活動滑動到第二個活動時立即保存任務。Android:通過刷卡而不是按鈕保存表格數據
爲此,我已嘗試從活動中的OnPageChangeListener.onPageScrolled()
方法調用片段的saveTask()
方法,但片段中的所有視圖都提供NullPointerException
。如果我嘗試在活動的OnPageChangeListener.onPageScrollStateChanged()
的保存任務按鈕上嘗試performClick()
,則即使按鈕也會提供NullPointerException
。當我打印到日誌以查看「保存任務」按鈕是否已初始化時,日誌會正確顯示按鈕ID。我不知道如何使用滑動將任務保存到數據庫。請幫忙!
這是我的主要活動:
public class AddTask extends AppCompatActivity {
/**
* The {@link PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {@link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {@link FragmentStatePagerAdapter}.
*/
private static SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {@link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
public List<String> fragments = new Vector<String>();
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_task);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
//fill the fragments list with the fragment classes
fragments.add(AddTaskFragment.class.getName());
fragments.add(TasksFragment.class.getName());
fragments.add(CommentsFragment.class.getName());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setOffscreenPageLimit(2);
mViewPager.setCurrentItem(1);
final AddTaskFragment addTaskFrag = (AddTaskFragment) mSectionsPagerAdapter.getItem(0);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
android.support.v7.app.ActionBar actionBar = getSupportActionBar();
switch (position) {
case 0:
actionBar.setTitle("Add New Task");
break;
case 1:
actionBar.setTitle("Existing Tasks");
break;
case 2:
actionBar.setTitle("Comments");
break;
}
}
@Override
public void onPageSelected(int position) {
if (fragments.get(position).equals(TasksFragment.class.getName())) {
}
}
@Override
public void onPageScrollStateChanged(int state) {
if(mViewPager.getCurrentItem()==0) {
if (state == ViewPager.SCROLL_STATE_DRAGGING) {
if (addTaskFrag != null) {
addTaskFrag.saveTaskBtn.performClick();
}
}
}
}
});
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_add_task, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onStart() {
super.onStart();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client.connect();
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"AddTask Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://com.example.ishita.assigntasks/http/host/path")
);
AppIndex.AppIndexApi.start(client, viewAction);
}
@Override
public void onStop() {
super.onStop();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"AddTask Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://com.example.ishita.assigntasks/http/host/path")
);
AppIndex.AppIndexApi.end(client, viewAction);
client.disconnect();
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public List<String> fragmentsA;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
fragmentsA = fragments;
}
@Override
public Fragment getItem(int position) {
//Instantiate the fragment at the position where the pager is.
return Fragment.instantiate(getApplicationContext(), fragmentsA.get(position));
}
@Override
public int getCount() {
// return how many fragments there are in the tabbed activity
return fragmentsA.size();
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Add Task";
case 1:
return "Tasks List";
case 2:
return "Comments";
}
return null;
}
}
}
這裏是我的片段形式的Java創建一個新的類:
/**
* A placeholder fragment containing a simple view.
*/
public class AddTaskFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
final int PICK_CONTACT = 1;
private static final String ARG_SECTION_NUMBER = "section_number";
public String mAssigneeName;
public String mAssigneeContact;
public String mTaskName;
public String mDueDate;
public String mComments = null;
public AddTaskFragment() {
}
EditText dueDate;
EditText assignee;
EditText taskDescription;
EditText comments;
Button saveTaskBtn;
View rootView;
Calendar myCalendar = Calendar.getInstance();
DatePickerDialog.OnDateSetListener date = new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear,
int dayOfMonth) {
// TODO Auto-generated method stub
myCalendar.set(Calendar.YEAR, year);
myCalendar.set(Calendar.MONTH, monthOfYear);
myCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
updateLabel();
}
};
private void updateLabel() {
String displayFormat = "MMM dd, yyyy"; //setting the format in which the date will be displayed
SimpleDateFormat sdf = new SimpleDateFormat(displayFormat, Locale.US);
dueDate.setText(sdf.format(myCalendar.getTime()));
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static AddTaskFragment newInstance(int sectionNumber) {
AddTaskFragment fragment = new AddTaskFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_add_task, container, false);
dueDate = (EditText) rootView.findViewById(R.id.due_date);
taskDescription = (EditText) rootView.findViewById(R.id.description);
comments = (EditText) rootView.findViewById(R.id.comments);
assignee = (EditText) rootView.findViewById(R.id.assignee);
dueDate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new DatePickerDialog(getActivity(), date, myCalendar
.get(Calendar.YEAR), myCalendar.get(Calendar.MONTH),
myCalendar.get(Calendar.DAY_OF_MONTH)).show();
}
}
);
assignee.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
startActivityForResult(intent, PICK_CONTACT);
} catch (Exception e) {
e.printStackTrace();
}
}
});
saveTaskBtn = (Button) rootView.findViewById(R.id.save_task);
Log.v("AddTaskFragment", "saveTaskBtn assigned to " + R.id.save_task);
saveTaskBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
saveTask();
}
});
return rootView;
}
public void saveTask(){
try {
mTaskName = taskDescription.getText().toString();
taskDescription.setText("");
mDueDate = dueDate.getText().toString();
dueDate.setText("");
mComments = comments.getText().toString();
comments.setText("");
assignee.setText(R.string.assignee_prompt);
if (mTaskName == null || mDueDate == null || mAssigneeName == null) {
Toast.makeText(getContext(), "Fields cannot be empty. Please fill some values.", Toast.LENGTH_SHORT).show();
} else {
UpdateTask updateDB = new UpdateTask();
updateDB.execute();
Toast.makeText(getContext(), "Task saved.", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void onActivityResult(int reqCode, int resultCode, Intent data) {
super.onActivityResult(reqCode, resultCode, data);
EditText assignee = (EditText) getActivity().findViewById(R.id.assignee);
switch (reqCode) {
case (PICK_CONTACT):
if (resultCode == Activity.RESULT_OK) {
Uri contactData = data.getData();
Cursor cursor = getContext().getContentResolver().query(contactData, new String[]{ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}, null, null, null);
if (cursor.moveToFirst()) {
mAssigneeName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
mAssigneeContact = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER));
assignee.setText(mAssigneeName);
Toast.makeText(getActivity(), mAssigneeName + " has number " + mAssigneeContact, Toast.LENGTH_LONG).show();
}
cursor.close();
}
break;
}
}
public class UpdateTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
ContentValues taskDetails = new ContentValues();
taskDetails.put(TasksContract.TaskEntry.COL_DESCRIPTION, mTaskName);
taskDetails.put(TasksContract.TaskEntry.COL_ASSIGNEE_KEY, mAssigneeContact);
taskDetails.put(TasksContract.TaskEntry.COL_CREATOR_KEY, "creatorID");
taskDetails.put(TasksContract.TaskEntry.COL_DUE_DATE, mDueDate);
taskDetails.put(TasksContract.TaskEntry.COL_COMMENTS, mComments);
getContext().getContentResolver().insert(TasksContract.TaskEntry.CONTENT_URI, taskDetails);
Cursor cursor = getContext().getContentResolver().query(
TasksContract.ProfileEntry.CONTENT_URI,
new String[]{TasksContract.ProfileEntry._ID},
TasksContract.ProfileEntry.COL_CONTACT + "=?",
new String[]{mAssigneeContact},
null
);
if (!cursor.moveToFirst()) {
ContentValues contactDetails = new ContentValues();
contactDetails.put(TasksContract.ProfileEntry.COL_NAME, mAssigneeName);
contactDetails.put(TasksContract.ProfileEntry.COL_CONTACT, mAssigneeContact);
getContext().getContentResolver().insert(TasksContract.ProfileEntry.CONTENT_URI, contactDetails);
}
cursor.close();
return null;
}
}
}
這裏是碎片的XML:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.ishita.assigntasks.AddTaskFragment">
<EditText
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:hint="@string/task_prompt" />
<EditText
android:id="@+id/assignee"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:ems="10"
android:focusable="false"
android:inputType="textPersonName"
android:text="@string/assignee_prompt" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal">
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/due_date"
android:textSize="18sp" />
<EditText
android:id="@+id/due_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:ems="10"
android:focusable="false"
android:inputType="date" />
</LinearLayout>
<EditText
android:id="@+id/comments"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:hint="@string/comments"
android:minHeight="?android:listPreferredItemHeight" />
<Button
android:id="@+id/save_task"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/save_task" />
</LinearLayout>
</ScrollView>
LogCat:
02-18 13:48:05.538 3752-3752/? I/art: Late-enabling -Xcheck:jni
02-18 13:48:05.628 3752-3752/com.example.ishita.assigntasks W/ResourceType: Found multiple library tables, ignoring...
02-18 13:48:05.664 3752-3752/com.example.ishita.assigntasks I/GMPM: App measurement is starting up, version: 8487
02-18 13:48:05.664 3752-3752/com.example.ishita.assigntasks I/GMPM: To enable debug logging run: adb shell setprop log.tag.GMPM VERBOSE
02-18 13:48:05.823 3752-3788/com.example.ishita.assigntasks D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
02-18 13:48:05.840 3752-3752/com.example.ishita.assigntasks D/Atlas: Validating map...
02-18 13:48:06.039 3752-3788/com.example.ishita.assigntasks I/Adreno-EGL: <qeglDrvAPI_eglInitialize:410>: EGL 1.4 QUALCOMM build: AU_LINUX_ANDROID_LA.BF.1.1.1_RB1.05.01.00.042.030_msm8974_LA.BF.1.1.1_RB1__release_AU()
OpenGL ES Shader Compiler Version: E031.25.03.06
Build Date: 05/17/15 Sun
Local Branch: mybranch10089422
Remote Branch: quic/LA.BF.1.1.1_rb1.22
Local Patches: NONE
Reconstruct Branch: AU_LINUX_ANDROID_LA.BF.1.1.1_RB1.05.01.00.042.030 + 6151be1 + NOTHING
02-18 13:48:06.053 3752-3788/com.example.ishita.assigntasks I/OpenGLRenderer: Initialized EGL, version 1.4
02-18 13:48:06.077 3752-3788/com.example.ishita.assigntasks D/OpenGLRenderer: Enabling debug mode 0
02-18 13:48:06.123 3752-3752/com.example.ishita.assigntasks W/View: requestLayout() improperly called by android.widget.TextView{5fbdde1 V.ED.... ......ID 48,43-403,124} during layout: running second layout pass
02-18 13:48:06.440 3752-3752/com.example.ishita.assigntasks V/case:msgCount:getInt: 0
02-18 13:48:06.440 3752-3752/com.example.ishita.assigntasks V/getViewId: 2131493003
02-18 13:48:06.485 3752-3752/com.example.ishita.assigntasks I/Timeline: Timeline: Activity_idle id: [email protected] time:19983548
02-18 13:48:10.458 3752-3752/com.example.ishita.assigntasks E/InputEventReceiver: Exception dispatching input event.
02-18 13:48:10.458 3752-3752/com.example.ishita.assigntasks D/AndroidRuntime: Shutting down VM
02-18 13:48:10.532 3752-3752/com.example.ishita.assigntasks E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.ishita.assigntasks, PID: 3752
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.widget.Button.performClick()' on a null object reference
at com.example.ishita.assigntasks.AddTask$1.onPageScrollStateChanged(AddTask.java:100)
at android.support.v4.view.ViewPager.dispatchOnScrollStateChanged(ViewPager.java:1811)
at android.support.v4.view.ViewPager.setScrollState(ViewPager.java:404)
at android.support.v4.view.ViewPager.onInterceptTouchEvent(ViewPager.java:1935)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1961)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2406)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2107)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2406)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2107)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2406)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2107)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2406)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2107)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2406)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2107)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2406)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2107)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2372)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1722)
at android.app.Activity.dispatchTouchEvent(Activity.java:2742)
at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:60)
at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:60)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2333)
at android.view.View.dispatchPointerEvent(View.java:8742)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4136)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4002)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3557)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3610)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3576)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3693)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3584)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3750)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3557)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3610)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3576)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3584)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3557)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5823)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5797)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5768)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5913)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:176)
at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:5884)
at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:5936)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:548)
添加logcat,請 – yennsarah
文本限制不允許。這是要點: 致命例外:主要 進程:com.example.ishita.assigntasks,PID:3752 java.lang.NullPointerException:嘗試調用虛擬方法'布爾android.widget.Button.performClick()'上空對象引用 at com.example.ishita.assigntasks.AddTask $ 1.onPageScrollStateChanged(AddTask.java:100) saveTaskBtn –
刪除一些導入語句後添加logcat。 –