0

在 onOptionsItemSelected 方法中调用对话框片段。从那里开始,当调用 sql db 时,日期选择器和清除历史片段似乎都获得了空指针。

主要活动和 dialogFrag 类如下所示。堆栈跟踪底部的错误也是:

主要活动:

package com.example.charl.walkthisway;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;


import java.sql.Date;

import Dialogs.ClearHistoryWarning;
import Dialogs.DatePickerTestMode;
import Models.DbManager;
import SystemDateStrategy.SystemDatePreferenceManager;
import Tabs.Goal;
import Tabs.History;
import Tabs.MainTabsLayout;

import static com.example.charl.walkthisway.R.id.stats;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener, DatePickerTestMode.OnCompleteListener,
        ClearHistoryWarning.OnCompleteListener {

    DbManager db = new DbManager(this, null, null, DbManager.DATABASE_VERSION);
    SystemDatePreferenceManager util = new SystemDatePreferenceManager();

    History history = new History();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        util.mainModeDate(this);

        // Nav drawer!
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        displaySelectedScreen(R.id.walk);
        db = new DbManager(this, null, null, 2);

    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, 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();

        if (item.isChecked()) item.setChecked(false);
        else item.setChecked(true);

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            Intent i = new Intent(this, SettingsPreferences.class);
            startActivity(i);
        }
        if (id == R.id.action_date_picker) {
            FragmentManager fm = getSupportFragmentManager();
            DatePickerTestMode dp = new DatePickerTestMode();
            //dp.setTargetFragment(new Goal(), 0);
            dp.show(fm, "date picker");
        }
        if (id == R.id.action_delete_history) {
            FragmentManager fm = getSupportFragmentManager();
            ClearHistoryWarning chw = new ClearHistoryWarning();
            chw.setTargetFragment(new History(), 0);
            chw.show(fm, "date picker");
        }


        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        //calling the method displayselectedscreen and passing the id of selected menu
        displaySelectedScreen(item.getItemId());
        return true;
    }

    private void displaySelectedScreen(int itemId) {

        //creating fragment object
        Fragment fragment = null;

        //initializing the fragment object which is selected
        switch (itemId) {
            case R.id.Settings:
                Intent i = new Intent(this, SettingsPreferences.class);
                startActivity(i);
                break;
            case R.id.walk:
                fragment = new MainTabsLayout();
                break;
            case stats:
                fragment = new Goal();
                break;
            case R.id.test:
                fragment = history;
                break;
        }

        /***
         * Use this section to replace the content main with different fragments:
         * remembering that any layouts in content_main will make all frags the
         * the same format
         */
        if (fragment != null) {
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.content_frame, fragment);
            ft.commit();
        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
    }

    @Override
    public void onComplete(Date boop) {
        Log.d("filter", "some date is: " + String.valueOf(boop));
        util.testModeDate(boop, this);
    }


    @Override
    public void onClearHistory(Boolean clearHistory) {
        if (clearHistory) {
            db.clearHistory();
            clearHistory = false;
        }
    }
}

日期选择器对话框片段:

   package Dialogs;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.DatePicker;
import android.widget.Toast;

import com.example.charl.walkthisway.R;

import Models.DbManager;
import SystemDateStrategy.SystemDateManager;
import SystemDateStrategy.SystemDatePreferenceManager;

import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Calendar;


public class DatePickerTestMode extends DialogFragment {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    SystemDatePreferenceManager util = new SystemDatePreferenceManager();

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;
    String dateString;
    Date someDate;
    private OnCompleteListener completeListener;
    DbManager db = new DbManager(this.getActivity().getApplicationContext(), null, null, DbManager.DATABASE_VERSION);

    public DatePickerTestMode() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment DatePickerTestMode.
     */
    // TODO: Rename and change types and number of parameters
    public static DatePickerTestMode newInstance(String param1, String param2) {
        DatePickerTestMode fragment = new DatePickerTestMode();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
        setHasOptionsMenu(true);

    }


    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        LayoutInflater inflater = getActivity().getLayoutInflater();
        View v = inflater.inflate(R.layout.fragment_date_picker, null);

        DatePicker datePicker = (DatePicker) v.findViewById(R.id.datePicker);
        Calendar calendar = Calendar.getInstance();

        datePicker.init(calendar.get(Calendar.YEAR),
                calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
                new DatePicker.OnDateChangedListener() {
                    @Override
                    public void onDateChanged(DatePicker datePicker, int year, int month, int dayOfMonth) {

                        someDate = new Date(year - 1900, month, dayOfMonth);

                        util.testModeDate(someDate, getContext());

                        SystemDateManager date = new SystemDateManager();
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        // dateString = sdf.format(someDate);
                        dateString = date.systemDateDecider(getContext());
                    }
                });

        db.minStat();


        builder.setView(v).setPositiveButton("Ok", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(getContext(), dateString, Toast.LENGTH_LONG);
                //DbManager db = new DbManager(getContext().getApplicationContext(), null, null, DbManager.DATABASE_VERSION);
                //db.minStat();
                completeListener.onComplete(someDate);
                dismiss();
            }
        }).setNegativeButton("cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(getContext(), "dis is cancel", Toast.LENGTH_LONG);
                dismiss();
            }
        });
        return builder.create();
    }


    public static interface OnCompleteListener {
        public abstract void onComplete(Date date);
    }

    // make sure the Activity implemented it


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            this.completeListener = (OnCompleteListener) context;
        } catch (final ClassCastException e) {
            throw new ClassCastException(context.toString() + " must implement OnCompleteListener");
        }
    }
}

堆栈跟踪:

 FATAL EXCEPTION: main
                  Process: com.example.charl.Goal, PID: 26338
                  java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.support.v4.app.FragmentActivity.getApplicationContext()' on a null object reference
                      at Dialogs.DatePickerTestMode.<init>(DatePickerTestMode.java:40)
                      at com.example.charl.walkthisway.MainActivity.onOptionsItemSelected(MainActivity.java:98)
                      at android.app.Activity.onMenuItemSelected(Activity.java:2895)
                      at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:406)
                      at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:195)
                      at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:103)
                      at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:103)
                      at android.support.v7.app.ToolbarActionBar$2.onMenuItemClick(ToolbarActionBar.java:69)
                      at android.support.v7.widget.Toolbar$1.onMenuItemClick(Toolbar.java:203)
                      at android.support.v7.widget.ActionMenuView$MenuBuilderCallback.onMenuItemSelected(ActionMenuView.java:762)
                      at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:810)
                      at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152)
                      at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:957)
                      at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:947)
                      at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:616)
                      at android.support.v7.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:153)
                      at android.view.View.performClick(View.java:4785)
                      at android.view.View$PerformClick.run(View.java:19884)
                      at android.os.Handler.handleCallback(Handler.java:746)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:135)
                      at android.app.ActivityThread.main(ActivityThread.java:5343)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at java.lang.reflect.Method.invoke(Method.java:372)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
Application terminated.
4

3 回答 3

0

您应该在以下位置初始化您的数据库助手onCreate()

public class DatePickerTestMode extends DialogFragment {

    private DbManager db;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        db = new DbManager(getActivity(), null, null, DbManager.DATABASE_VERSION);

        setHasOptionsMenu(true);

    }
}

请注意,我使用的是getActivity()因为 anActivityContext. 这是首选,除非您有特定的理由使用应用程序上下文。

于 2017-03-20T00:53:17.393 回答
0

对于其他未经培训的了解如何使用 android 的人,我有一个巨大的解决方法:

由于在附加片段之前无法调用 getActivity 我只是在另一个片段中使用了 onOptionsItemSelected 方法覆盖:

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.action_delete_history) {

            FragmentManager fm = getFragmentManager();
            ClearHistoryWarning clear = new ClearHistoryWarning();
            clear.setTargetFragment(History.this, 0);
            clear.show(fm, "Add New Goal");
        }
        return super.onOptionsItemSelected(item);
    }

关于活动结果:

    @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (resultCode == 0) {
                DbManager dbd = new DbManager(this.getActivity().getApplicationContext(), null, null, DbManager.DATABASE_VERSION);
                dbd.clearHistory();
                populateListView();
            }
            super.onActivityResult(requestCode, resultCode, data);
        }

populateListView() 只是从数据库中填充一个 cursorAdapter。

不要忘记使用:

    setHasOptionsMenu(true);

在 onCreateMethod 中。

从对话片段中,就在解雇之前,我有:

     getTargetFragment().onActivityResult(getTargetRequestCode(), 0, getActivity().getIntent());

以前的实施:

我之前的实现是使用一个接口,并在单击历史按钮时获取一个布尔值,然后将其发送到主活动以从其接口方法的实现中清除数据库。但这并没有让我立即更新片段中的视图,因为我必须向左滑动几次并返回(使用 tablayout 和 viewpager)以调用 onResume() 方法并随后调用我的 populateListView 方法。

于 2017-03-20T00:34:48.273 回答
0

DbManager db = new DbManager(this.getActivity().getApplicationContext(), null, null, DbManager.DATABASE_VERSION);

是错误。this.getActivity().getApplicationContext()在附加片段之前您不能调用

于 2017-03-20T00:10:14.263 回答