2016-04-19 3 views
1

У меня есть помощник class по имени Prefs, в котором у меня есть статический class member от interfaceSyncFinishedListener. Вот они:Невозможно инициализировать статический член в Java - Android

public interface SyncFinishedListener { 
    void onSyncFinished(); 
} 

вот мой Prefs вспомогательный класс

public class Prefs { 
    public static final String TAG = Prefs.class.getSimpleName(); 
    private static final String PrefsName = Prefs.class.getSimpleName(); 

    SharedPreferences mPrefs; 

    public Prefs(Context context) { 
     super(); 
     mPrefs = context.getSharedPreferences(PrefsName, Context.MODE_PRIVATE); 
    } 

    private static SyncFinishedListener listener; 

    public Prefs(Context context, SyncFinishedListener listener) { 
     this(context); 
     Prefs.listener = listener; 
     SyncUtils.get(context).requestSync(HrEmployee.AUTHORITY); 
    } 

    private boolean isSyncFinished() { 
     boolean isSyncFinished = (isHrEmployeeSyncFinished() 
       && isHrAttendanceSyncFinished() 
       && isAttReportSyncFinished() 
       && isSchoolSchoolSyncFinished() 
     ); 
     Log.e(TAG, "isSyncFinished is :" + isSyncFinished); 
     if (isSyncFinished) { 
      try { 
       setHrEmployeeSyncFinished(false); 
       setHrAttendanceSyncFinished(false); 
       setAttReportSyncFinished(false); 
       setSchoolSchoolSyncFinished(false); 
       // Here's NullPointerException 
       Prefs.listener.onSyncFinished(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
     return isSyncFinished; 
    } 

    private static final String HrEmployeeSyncFinished = "hrEmployeeSyncFinished"; 
    private static final String HrAttendanceSyncFinished = "hrAttendanceSyncFinished"; 
    private static final String AttReportSyncFinished = "attReportSyncFinished"; 
    private static final String SchoolSchoolSyncFinished = "schoolSchoolSyncFinished"; 

    private boolean isHrEmployeeSyncFinished() { 
     return mPrefs.getBoolean(HrEmployeeSyncFinished, false); 
    } 

    public Prefs setHrEmployeeSyncFinished(boolean hrEmployeeSyncFinished) { 
     mPrefs.edit().putBoolean(HrEmployeeSyncFinished, hrEmployeeSyncFinished).apply(); 
     if (hrEmployeeSyncFinished) { 
      isSyncFinished(); 
     } 
     return this; 
    } 

    private boolean isHrAttendanceSyncFinished() { 
     return mPrefs.getBoolean(HrAttendanceSyncFinished, false); 
    } 

    public Prefs setHrAttendanceSyncFinished(boolean hrAttendanceSyncFinished) { 
     mPrefs.edit().putBoolean(HrAttendanceSyncFinished, hrAttendanceSyncFinished).apply(); 
     if (hrAttendanceSyncFinished) { 
      isSyncFinished(); 
     } 
     return this; 
    } 

    private boolean isAttReportSyncFinished() { 
     return mPrefs.getBoolean(AttReportSyncFinished, false); 
    } 

    public Prefs setAttReportSyncFinished(boolean attReportSyncFinished) { 
     mPrefs.edit().putBoolean(AttReportSyncFinished, attReportSyncFinished).apply(); 
     if (attReportSyncFinished) { 
      isSyncFinished(); 
     } 
     return this; 
    } 

    private boolean isSchoolSchoolSyncFinished() { 
     return mPrefs.getBoolean(SchoolSchoolSyncFinished, false); 
    } 

    public Prefs setSchoolSchoolSyncFinished(boolean schoolSchoolSyncFinished) { 
     mPrefs.edit().putBoolean(SchoolSchoolSyncFinished, schoolSchoolSyncFinished).apply(); 
     if (schoolSchoolSyncFinished) { 
      isSyncFinished(); 
     } 
     return this; 
    } 
}  

и вот как я называю это из Fragment

public class Employees extends BaseFragment { 

    private static final String TAG = Employees.class.getSimpleName(); 
    private Prefs mPrefs; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setHasOptionsMenu(true); 
     mPrefs = new Prefs(getContext()); 
    } 

    @Override 
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
     inflater.inflate(R.menu.menu_employee, menu); 
     super.onCreateOptionsMenu(menu, inflater); 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     int id = item.getItemId(); 
     if (id == R.id.action_sync) { 
      return onSync(); 
     } 
     return super.onOptionsItemSelected(item); 
    } 

    private boolean onSync() { 
     try { 
      final ProgressDialog dialog = new ProgressDialog(getContext(), R.style.AppDialogTheme); 
      dialog.setTitle("Please Wait"); 
      dialog.setMessage("Syncing Data"); 
      dialog.setCancelable(false); 
      dialog.show(); 

      new Prefs(getContext(), new SyncFinishedListener() { 
       @Override 
       public void onSyncFinished() { 
        // Not getting called 
        dialog.dismiss(); 
        getActivity().finish(); 
       } 
      }); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return true; 
    } 
} 

Мой код должен работать нормально. но я не могу понять, почему я получаю NullPointerException. Вот некоторые Log для отладки.

E/HrEmployee: onSyncStarted 
E/HrAttendance: onSyncStarted 
E/SchoolSchool: onSyncStarted 
E/SchoolSchool: onSyncFinished 
E/Prefs: isSyncFinished is :false 
E/HrEmployee: onSyncFinished 
E/Prefs: isSyncFinished is :false 
E/AttReport: onSyncStarted 
E/HrEmployee: onSyncStarted 
E/HrEmployee: onSyncFinished 
E/Prefs: isSyncFinished is :false 
E/HrAttendance: onSyncStarted 
E/HrAttendance: onSyncFinished 
E/Prefs: isSyncFinished is :false 
E/SchoolSchool: onSyncStarted 
E/SchoolSchool: onSyncFinished 
E/Prefs: isSyncFinished is :false 
E/AttReport: onSyncStarted 
E/HrEmployee: onSyncStarted 
E/HrEmployee: onSyncStarted 
E/HrEmployee: onSyncFinished 
E/Prefs: isSyncFinished is :false 
E/HrAttendance: onSyncStarted 
E/HrEmployee: onSyncFinished 
E/Prefs: isSyncFinished is :false 
E/AttReport: onSyncStarted 
E/AttReport: onSyncFinished 
E/Prefs: isSyncFinished is :false 
E/HrAttendance: onSyncFinished 
E/Prefs: isSyncFinished is :false 
E/HrAttendance: onSyncStarted 
E/HrAttendance: onSyncFinished 
E/Prefs: isSyncFinished is :false 
E/SchoolSchool: onSyncStarted 
E/SchoolSchool: onSyncFinished 
E/Prefs: isSyncFinished is :false 
E/HrAttendance: onSyncFinished 
E/Prefs: isSyncFinished is :false 
E/AttReport: onSyncFinished 
E/Prefs: isSyncFinished is :true 
W/System.err: java.lang.NullPointerException: Attempt to invoke interface method 'void com.odoo.addons.employees.utils.SyncFinishedListener.onSyncFinished()' on a null object reference 
W/System.err:  at com.odoo.addons.employees.utils.Prefs.isSyncFinished(Prefs.java:145) 
W/System.err:  at com.odoo.addons.employees.utils.Prefs.setAttReportSyncFinished(Prefs.java:115) 
W/System.err:  at com.odoo.addons.employees.models.AttReport.onSyncFinished(AttReport.java:58) 
W/System.err:  at com.odoo.core.service.OSyncAdapter.syncData(OSyncAdapter.java:291) 
W/System.err:  at com.odoo.core.service.OSyncAdapter.onPerformSync(OSyncAdapter.java:204) 
W/System.err:  at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:272) 
+1

Я думаю, что код тоже должен работать. так что, возможно, где-то еще вы не заметили, что set 'listener' имеет значение null. добавьте 'logcat' перед настройкой' listenener' и повторите попытку. –

+0

Внутри открытого конструктора 'Prefs (контекст контекста)' вы не инициализируете список слушателей. Это может вызвать проблему в 'isSyncFinished', где вы ее используете. – uniknow

ответ

0

Попытка отследить ошибку назад к корню: Вы получаете в NPE, потому что ваша Prefs.listener вар равна нулю при вызове onSyncFinished() на нем (в isSyncFinished()). Эта переменная назначается в конструкторе, который принимает второй параметр прослушивателя. Но есть также конструктор, который принимает только контекст как параметр, и если этот используется, то Prefs.listener остается нулевым. В вашем фрагменте вы создаете Prefs-Object с этим конструктором в onCreate(). Это единственная причина, по которой я могу видеть Prefs.listener как null. Поскольку ваш Prefs.listener статичен, вы должны убедиться, что конструктор с назначением слушателя вызывается до того, как вызывается isSyncFinished() другого объекта Prefs.

Надеюсь, что смогу помочь.

PS: Но для назначения статической переменной в конструкторе и надеемся, что этот var инициализирован для объекта, который не вызвал этот конструктор, не является хорошим способом реализовать то, что вы хотите. Нужно ли для слушателя быть статичным?

0

Во-первых, нет причин, по которым вы должны называть super() в первом конструкторе, поскольку вы не распространяете какой-либо класс.

Во-вторых, нет причин, по которым listener должен быть статическим, в этом коде как минимум. Если вы вызываете Prefs.listener снаружи этого кода, вы должны пересмотреть всю свою архитектуру, удалив статические вызовы. Это плохая привычка, которую можно почти всегда избегать. Если класс имеет только статические переменные, которые используются по всему вашему приложению, вы должны подумать об использовании шаблона проектирования singleton. Его легко и безопасно использовать, как только вы привыкнете к нему.

Смежные вопросы