5

Cuando intento para conseguir un color mediante getResources().getColor(R.color.yellow) en una actividad normal me sale esta excepción:NullPointerException en android.content.ContextWrapper

07-12 11:58:38.019: E/AndroidRuntime(3233): FATAL EXCEPTION: main 
07-12 11:58:38.019: E/AndroidRuntime(3233): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.moveinblue.planner/com.moveinblue.planner.controller.plan.PlanDayScreen}: java.lang.NullPointerException 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1993) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2104) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.ActivityThread.access$600(ActivityThread.java:132) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1157) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.os.Handler.dispatchMessage(Handler.java:99) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.os.Looper.loop(Looper.java:137) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.ActivityThread.main(ActivityThread.java:4575) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at java.lang.reflect.Method.invokeNative(Native Method) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at java.lang.reflect.Method.invoke(Method.java:511) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at dalvik.system.NativeStart.main(Native Method) 
07-12 11:58:38.019: E/AndroidRuntime(3233): Caused by: java.lang.NullPointerException 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.content.ContextWrapper.getResources(ContextWrapper.java:81) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at com.moveinblue.planner.controller.plan.PlanDayScreen$4.<init>(PlanDayScreen.java:408) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at com.moveinblue.planner.controller.plan.PlanDayScreen.<init>(PlanDayScreen.java:406) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at java.lang.Class.newInstanceImpl(Native Method) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at java.lang.Class.newInstance(Class.java:1319) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.Instrumentation.newActivity(Instrumentation.java:1023) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1984) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  ... 11 more 

¿Alguien puede darme alguna retrospectiva aquí? Estoy totalmente perdido.

Código

en la actividad:

package com.moveinblue.planner.controller.plan; 

import java.text.SimpleDateFormat; 
import java.util.BitSet; 
import java.util.Calendar; 

import android.app.AlertDialog; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.os.AsyncTask; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.ArrayAdapter; 
import android.widget.AutoCompleteTextView; 
import android.widget.ImageButton; 
import android.widget.ImageView; 
import android.widget.ListView; 
import android.widget.Toast; 

import com.moveinblue.api.Login; 
import com.moveinblue.api.Planner; 
import com.moveinblue.api.UnauthorizedException; 
import com.moveinblue.api.io.InvalidURLException; 
import com.moveinblue.api.io.OfflineException; 
import com.moveinblue.api.model.ModelObject; 
import com.moveinblue.api.model.Plan; 
import com.moveinblue.api.model.time.Day; 
import com.moveinblue.api.model.time.ScheduledThingToDo; 
import com.moveinblue.api.model.time.ScheduledTime; 
import com.moveinblue.api.model.time.ScheduledTime.TimeOfDay; 
import com.moveinblue.planner.R; 
import com.moveinblue.planner.controller.GenericPlannerScreen; 
import com.moveinblue.planner.controller.thingtodo.ThingsToDoListScreen; 
import com.moveinblue.planner.controller.user.LoginScreen; 
import com.moveinblue.planner.ui.actionbar.ActionBar; 
import com.moveinblue.planner.ui.draganddroplist.DragListener; 
import com.moveinblue.planner.ui.draganddroplist.DragNDropListView; 
import com.moveinblue.planner.ui.draganddroplist.DropListener; 
import com.moveinblue.planner.ui.draganddroplist.RemoveListener; 
import com.moveinblue.planner.utils.CommonActionStorage; 
import com.moveinblue.planner.utils.CurrentItemsStorage; 
import com.moveinblue.planner.utils.adapter.DragNDropAdapter; 
import com.moveinblue.planner.utils.adapter.listeners.OnCheckListener; 

public class PlanDayScreen extends GenericPlannerScreen { 

DragNDropListView lista; 
AutoCompleteTextView actv; 
String[] dests; 
DragNDropAdapter adapter; 
private Boolean idDroppedOrDeleted = false; 
private BitSet checkedBoxes = new BitSet(); 
private boolean firstLoad = true; 
Day day; 
@SuppressWarnings("unused") 
private static final String LOG_TAG = PlanDayScreen.class 
     .getCanonicalName(); 

@Override 
public void load() { 
    setContentView(R.layout.plan_day_list); 
    setUpList(); 
    setUpBottomLayout(false); 
    lista.requestFocus(); 
} 

@Override 
protected void loadActionBar() { 
    Plan p = CurrentItemsStorage.currentPlan; 
    Calendar c = CurrentItemsStorage.currentDay; 
    ab = new ActionBar(this, ActionBar.TYPE_LIST); 
    String date = new SimpleDateFormat("MMM dd, yyyy").format(c.getTime()); 
    date = Character.toUpperCase(date.charAt(0)) + date.substring(1); 
    date = "(" + date + ")"; 
    String title; 

    title = (p != null) ? p.name + " " + date : "Draft plan"; 

    ab.setTitle(title); 
    ab.setBackAction(R.drawable.back, new OnClickListener() { 

     @Override 
     public void onClick(View arg0) { 
      Intent intent = new Intent(PlanDayScreen.this, 
        PlanTabsScreen.class); 
      intent.putExtra("tab", 2); 
      startActivity(intent); 
      overridePendingTransition(android.R.anim.slide_in_left, 
        android.R.anim.fade_out); 

     } 
    }); 
    CommonActionStorage.setUpActionBar(ab); 
} 

private void addNewTTD() { 
    if (getIntent().getBooleanExtra("schedule", false) && firstLoad) { 
     try { 
      Calendar c = CurrentItemsStorage.currentDay; 
      TimeOfDay tod = CurrentItemsStorage.currentTimeOfDaySelectedOption; 
      Planner.schedule(
        CurrentItemsStorage.getCurrentThingToDo().ttdId, 
        new ScheduledTime(c, tod)); 
     } catch (Exception ex) { 
      ex.getStackTrace(); 
     } 
    } 
    firstLoad = false; 
} 

/** 
* Sets up a bottom bar button 
* 
* @param id 
*   The bottom bar button id you want to set 
*/ 
private void setUpBottomButton(int id) { 
    ImageButton b = (ImageButton) findViewById(id); 
    switch (id) { 
    case R.id.buttonBottom1: 
     if (!areThereCheckedBoxes()) { 
      b.setOnClickListener(new OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        // Add TTD to plan 
        Intent intent = new Intent(PlanDayScreen.this, 
          ThingsToDoListScreen.class); 
        startActivity(intent); 
       } 
      }); 
     } else { 
      b.setOnClickListener(new OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        // Date 
       } 
      }); 
     } 
     break; 
    case R.id.buttonBottom2: 
     if (!areThereCheckedBoxes()) { 
      b.setOnClickListener(new OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        // Map 
        if (day != null) { 
         CurrentItemsStorage.mapModelObjects = new ModelObject[0]; 
         CurrentItemsStorage.mapModelObjects[1] = day; 
         Intent intent = new Intent(PlanDayScreen.this, 
           PlanTabsScreen.class); 
         startActivity(intent); 
        } 

       } 
      }); 
     } else { 
      b.setOnClickListener(new OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        // Confirm 
        new AlertDialog.Builder(PlanDayScreen.this) 
          .setIcon(android.R.drawable.ic_dialog_alert) 
          .setTitle(
            "Remove " + checkedCount() 
              + " things to do") 
          .setMessage(
            "Do you really wish to remove " 
              + checkedCount() 
              + " things to do from your plan?") 
          .setPositiveButton("Yes", 
            new DialogInterface.OnClickListener() { 

             @Override 
             public void onClick(
               DialogInterface dialog, 
               int which) { 
              // Remove 
              for (int i = 0; i < lista 
                .getCount(); i++) { 
               if (checkedBoxes.get(i)) { 
                // Get checked item 
                Object ttd = adapter 
                  .getItem(i); 
                if (ttd instanceof ScheduledThingToDo) { 
                 try { 
                  // Remove it 
                  ScheduledThingToDo tTD = (ScheduledThingToDo) ttd; 
                  Planner.unschedule(
                    tTD.ttdId, 
                    tTD.time); 
                 } catch (OfflineException ex) { 
                  Toast.makeText(
                    PlanDayScreen.this, 
                    getResources() 
                      .getString(
                        R.string.unschedule_error), 
                    Toast.LENGTH_SHORT) 
                    .show(); 
                 } catch (InvalidURLException e) { 
                 } 
                } 
               } 
              } 
              // Reset checkedBoxes and 
              // BottomLayout 
              checkedBoxes = new BitSet(); 
              setUpBottomLayout(false); 
              // Redraws the list 
              setUpList(); 
             } 
            }).setNegativeButton("No", null).show(); 
       } 
      }); 
     } 
     break; 
    case R.id.buttonBottom3: 
     b.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       // Update 

      } 

     }); 
     break; 
    } 
} 

/** 
* Sets up the list 
*/ 
private void setUpList() { 
    lista = (DragNDropListView) findViewById(R.id.listViewAgenda); 
    new LoadList(); 
} 

/** 
* Counts the number of checked boxes 
* 
* @return the number of checked boxes 
*/ 
private int checkedCount() { 
    int x = 0; 
    for (int i = 0; i < checkedBoxes.length(); i++) { 
     x += checkedBoxes.get(i) ? 1 : 0; 
    } 
    return x; 
} 

/** 
* Changes the buttoms on the bottom action bar. If you pass true, you get 
* the "delete items" action bar. Else, you get the "add items" action bar. 
* 
* @param isAnythingMarked 
*   True if you want to delete items, false if you want to add 
*   them. 
*/ 
private void setUpBottomLayout(boolean isAnythingMarked) { 
    ImageButton b1 = (ImageButton) findViewById(R.id.buttonBottom1); 
    ImageButton b2 = (ImageButton) findViewById(R.id.buttonBottom2); 
    ImageButton b3 = (ImageButton) findViewById(R.id.buttonBottom3); 
    b1.setImageDrawable(getResources().getDrawable(
      isAnythingMarked ? R.drawable.action_plans 
        : R.drawable.action_add)); 
    b2.setImageDrawable(getResources().getDrawable(
      isAnythingMarked ? R.drawable.action_delete 
        : R.drawable.action_map)); 
    b3.setImageDrawable(getResources() 
      .getDrawable(R.drawable.action_reload)); 
    setUpBottomButton(R.id.buttonBottom1); 
    setUpBottomButton(R.id.buttonBottom2); 
    setUpBottomButton(R.id.buttonBottom3); 
} 

private boolean areThereCheckedBoxes() { 
    for (int i = 0; i < checkedBoxes.length(); i++) { 
     if (checkedBoxes.get(i)) { 
      return true; 
     } 
    } 
    return false; 
} 

public void clickControlRowHandler(View v) { 
    Intent intent = new Intent(PlanDayScreen.this, 
      ThingsToDoListScreen.class); 
    startActivity(intent); 
} 

/** 
* Drop Listener for the DragNDropListView 
*/ 
private DropListener mDropListener = new DropListener() { 
    public void onDrop(final int from, int to) { 
     if (to == 0) 
      to = 1; 
     // If initial position is the same as final position, do nothing. 
     if (to != from) { 
      if (adapter instanceof DragNDropAdapter) { 
       if (adapter.getItem(from) instanceof ScheduledThingToDo) { 
        new DropCall(from, to); 
        ((DragNDropAdapter) adapter).onDrop(from, to); 
       } 
      } 
     } 
    } 
}; 

public OnClickListener onClickSave = new OnClickListener() { 

    public void onClick(View v) { 
     try { 
      if (Login.isRegistered()) { 
       if (Planner.loadPlan().name == null) { 
        CurrentItemsStorage.shallGoAfterCreatePlan = PlanDayScreen.class; 
        if (idDroppedOrDeleted) { 
         manageListChanges(); 
        } 
        Intent intent = new Intent(PlanDayScreen.this, 
          SavePlanScreen.class); 
        startActivity(intent); 
        return; 
       } 
      } else { 
       CurrentItemsStorage.currentPlan = Planner.loadPlan(); 
       CurrentItemsStorage.shallGoAfterLogin = PlanDayScreen.class; 
       Intent intent = new Intent(PlanDayScreen.this, 
         LoginScreen.class); 
       startActivity(intent); 
      } 

     } catch (OfflineException e) { 
      Toast.makeText(PlanDayScreen.this, 
        getResources().getString(R.string.plan_error), 
        Toast.LENGTH_SHORT).show(); 
     } 
     if (idDroppedOrDeleted) { 
      manageListChanges(); 
     } 
    } 
}; 

/** 
* Unschedules every TTD, then schedules it again. 
*/ 
private void manageListChanges() { 

    for (int i = 0; i < adapter.getCount(); i++) { 
     Object item = adapter.getItem(i); 
     if (item instanceof ScheduledThingToDo) { 
      try { 
       ScheduledThingToDo scheduled = (ScheduledThingToDo) item; 
       Planner.unschedule(scheduled.getId(), scheduled.time); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
    int state = 0; 
    for (int it = 0; it < adapter.getCount(); it++) { 
     Object item = adapter.getItem(it); 
     TimeOfDay tod = TimeOfDay.morning; 
     if (item instanceof ScheduledThingToDo) { 
      switch (state) { 
      case 1: 
       tod = TimeOfDay.morning; 
       break; 
      case 2: 
       tod = TimeOfDay.afternoon; 
       break; 
      case 3: 
       tod = TimeOfDay.evening; 
       break; 
      } 
      try { 
       Planner.schedule(((ScheduledThingToDo) item).ttdId, 
         new ScheduledTime(CurrentItemsStorage.currentDay, 
           tod)); 
      } catch (OfflineException e) { 
       Toast.makeText(PlanDayScreen.this, "No connection", 
         Toast.LENGTH_SHORT).show(); 
      } 
     } else { 
      state++; 
     } 
    } 
} 

/** 
* RemoveListener for the DragNDropListView 
*/ 
private RemoveListener mRemoveListener = new RemoveListener() { 
    public void onRemove(int which) { 
     // ListAdapter adapter = getListAdapter(); 
     if (adapter instanceof DragNDropAdapter) { 
      ((DragNDropAdapter) adapter).onRemove(which); 
      lista.invalidateViews(); 
     } 
    } 
}; 

/** 
* DragListener for the DragNDropListView 
*/ 
private DragListener mDragListener = new DragListener() { 

    int backgroundColor = getResources().getColor(R.color.yellow); 
    int defaultBackgroundColor = getResources().getColor(R.color.blue_bg); 

    public void onDrag(int x, int y, ListView listView) { 
     // TODO Auto-generated method stub 
    } 

    public void onStartDrag(View itemView) { 
     itemView.setVisibility(View.INVISIBLE); 
     itemView.setBackgroundColor(backgroundColor); 
     ImageView iv = (ImageView) itemView.findViewById(R.id.imageView1); 
     if (iv != null) 
      iv.setVisibility(View.INVISIBLE); 
    } 

    public void onStopDrag(View itemView) { 
     itemView.setVisibility(View.VISIBLE); 
     itemView.setBackgroundColor(defaultBackgroundColor); 
     ImageView iv = (ImageView) itemView.findViewById(R.id.imageView1); 
     if (iv != null) 
      iv.setVisibility(View.VISIBLE); 
    } 
}; 

private class LoadList extends AsyncTask<Void, Void, Void> { 

    public LoadList() { 
     execute(); 
    } 

    @Override 
    protected void onPreExecute() { 
     String[] x = { "Loading..." }; 
     addNewTTD(); 
     ArrayAdapter<String> asdf = new ArrayAdapter<String>(
       PlanDayScreen.this, R.layout.add_more, x); 
     lista.setAdapter(asdf); 
    } 

    @Override 
    protected Void doInBackground(Void... arg0) { 
     ScheduledThingToDo[] ttds; 
     try { 
      try { 
       // Loads current day 
       day = Planner.loadDay(CurrentItemsStorage.currentDay); 
       ttds = day.ttds; 
      } catch (NullPointerException ex) { 
       // No current day: Loads today 
       Day day = Planner.loadDay(Calendar.getInstance()); 
       ttds = day.ttds; 
      } 
     } catch (OfflineException e) { 
      // Offline 
      Toast.makeText(PlanDayScreen.this, 
        getResources().getString(R.string.day_error), 
        Toast.LENGTH_SHORT).show(); 
      ttds = new ScheduledThingToDo[0]; 
     } catch (UnauthorizedException e) { 
      // Something strange happened 
      ttds = new ScheduledThingToDo[0]; 
     } catch (Exception e) { 
      // Something even more strange happened 
      ttds = new ScheduledThingToDo[0]; 
     } 

     adapter = new DragNDropAdapter(PlanDayScreen.this, 
       new int[] { R.layout.dragitemttd }, ttds); 

     adapter.setOnCheckListener(new OnCheckListener() { 

      @Override 
      public void onCheck(boolean isChecked, int position) { 
       checkedBoxes.set(position, isChecked); 
       setUpBottomLayout(areThereCheckedBoxes()); 
      } 
     }); 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void result) { 
     lista.setAdapter(adapter); 
     lista.setDropListener(mDropListener); 
     lista.setRemoveListener(mRemoveListener); 
     lista.setDragListener(mDragListener); 

    } 

} 

private class DropCall extends AsyncTask<Void, Void, Void> { 

    private int from, to; 

    public DropCall(int from, int to) { 
     this.from = from; 
     this.to = to; 
     execute(); 
     lista.invalidateViews(); 
    } 

    @Override 
    protected Void doInBackground(Void... arg0) { 
     changeScheduledTTD(from, to); 
     return null; 
    } 

    /** 
    * Unschedules a TTD and then re-schedules it in its proper place 
    * 
    * @param from 
    *   The position the TTD came from 
    * @param to 
    *   The position the TTD has been dragged to 
    */ 
    protected void changeScheduledTTD(int from, int to) { 
     ScheduledThingToDo currentTTD; 
     if (adapter.getItem(to) instanceof ScheduledThingToDo) 
      currentTTD = (ScheduledThingToDo) adapter.getItem(to); 
     else 
      return; 

     int indexMorning = 0; 
     int indexAfternoon = 0; 
     int indexEvening = 0; 
     Object item = null; 
     String currentTime = null; 
     // Gets the indexes for Morning, Afternoon and Evening 
     for (int i = 0; i < adapter.getCount(); i++) { 
      item = adapter.getItem(i); 
      if (item instanceof String) { 
       currentTime = (String) item; 
       if (currentTime.equals("MORNING")) { 
        indexMorning = i; 
       } 
       if (currentTime.equals("AFTERNOON")) { 
        indexAfternoon = i; 
       } 
       if (currentTime.equals("EVENING")) { 
        indexEvening = i; 
       } 
      } 
     } 

     TimeOfDay tod = null; 
     if (to >= indexEvening) { 
      tod = TimeOfDay.evening; 
     } else if (to >= indexAfternoon) { 
      tod = TimeOfDay.afternoon; 
     } else if (to >= indexMorning) { 
      tod = TimeOfDay.morning; 
     } 
     if (!currentTTD.time.getTimeOfDay().equals(tod)) { 

      try { 
       Planner.unschedule(currentTTD.ttdId, currentTTD.time); 
       Planner.schedule(currentTTD.ttdId, new ScheduledTime(
         CurrentItemsStorage.currentDay, tod)); 
      } catch (OfflineException e) { 
       e.printStackTrace(); 
      } 

     } 
    } 
} 
} 
+0

¿Puede proporcionarnos el código de su actividad? – AMerle

+0

Hecho. Aunque es largo ;-) la excepción se lanza en la primera línea de código en la declaración mDragListener. – razielsarafan

+0

¿intentas ejecutar después de 'Limpiar' el proyecto? –

Respuesta

7

Su mDragListener es una variable miembro. En el momento de inicializar, el objeto/instancia Activity podría no estar listo. Por lo tanto, llamar al getResource() de la Actividad fallará.

// inner class or normal class ... change scope if needed 
private class DragListener { 
    int color = 0; 
    public DragListener(Context context) { 
     color = context.getResource().getColor(R.color.yellow); 
    } 
} 

// activity 
private DragListener mDragListener; 
public void onCreate(...) { 
    mDragListener = new DragListener(this); 
    // more code 
} 
+0

¿Cuáles son mis opciones entonces? – razielsarafan

+0

Haga que DragListener sea una clase interna privada con un constructor que tenga un parámetro de contexto. Dentro del constructor, inicializa los colores usando 'context.getResource()'. A continuación, inicialice la variable del oyente en la onCreate de su actividad. Las definiciones de clase anónimas como las que tiene no son reutilizables y, por lo tanto, solo son suficientes en situaciones muy específicas. Siempre trato de hacer que las clases sean reutilizables. – WarrenFaith

-4
int backgroundColor = Color.YELLOW; 

en lugar de

int backgroundColor = getResources().getColor(R.color.yellow); 
+3

¿Quién dijo que 'R.color.yellow == Color.YELLOW'? – WarrenFaith

+1

R.color.yellow NO es Color.Y AMARILLO. Ni siquiera cerca. – razielsarafan

+0

Esto no es una solución al problema de OPs. Su problema fue llamar a getResources() antes de que se inicializara el contexto. –

Cuestiones relacionadas