我遇到了Fragment和AsyncTask問題。問題是我正在創建一個Fragment來運行一個AsyncTask來運行一個計時器。該代碼獨立於我的所有其他代碼工作,並且我已經測試過無數次。問題是,當我把我的新代碼到我的應用程序,我在這一點上得到一個空指針:在啓動AsyncTask時獲取空指針異常,儘管看起來onCreate似乎包含所有變量
public void onClick(View v) {
if(v==abbtn){
aboutFragDialog();
}else if(v==exbtn){
finish();
}else if(v==starest){
if(mTaskFragment.isRunning()){
mTaskFragment.cancel();
} else {
mTaskFragment.start();
}if(v==mgextbtn){
mgcusd.dismiss();
}
}
}
是推動錯誤的實際行是:if(mTaskFragment.isRunning()){
。這個代碼鏈接到以下幾點:
public void replaceFrag(){
Bundle bundle = new Bundle();
String tester2 = String.valueOf(startTime).toString();
Log.i("VertygoEclypse - replaceFrag - Value for counter ", tester2);
if(tester2.matches("")){
bundle.putString("SecValue", "15");
} else {
bundle.putString("SecValue", tester2);
}
FragmentManager rfm = getSupportFragmentManager();
if(mTaskFragment == null){
TaskFragment mTaskFragment = new TaskFragment();
mTaskFragment.setArguments(bundle);
rfm.beginTransaction().add(mTaskFragment, "task").commit();
} else {
TaskFragment mTaskFragment = new TaskFragment();
mTaskFragment = (TaskFragment) rfm.findFragmentByTag("task");
mTaskFragment.setArguments(bundle);
rfm.beginTransaction().add(mTaskFragment, "task").commit();
}
}
此方法從以下稱爲:
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long l) {
switch(parent.getId()){
case R.id.timerspinner:
TimerDataBaseHandler isdb = new TimerDataBaseHandler(getApplicationContext());
SQLiteDatabase dbsec = isdb.getReadableDatabase();
int tagposition = s.getSelectedItemPosition()+1;
isdb.getReadableDatabase();
Cursor cc = dbsec.rawQuery("SELECT * FROM timers WHERE _id = "+tagposition, null);
if(cc.moveToFirst()){
setTimer(Integer.parseInt(cc.getString(2)));
starest.setEnabled(true);
replaceFrag();
}
}
}
上面的代碼就足夠了,在我的日誌TaskFragment活動我可以看到,我碰到送變量被視爲用作一個開始時間的倒計時,這是在這裏:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
bundle=getArguments();
i = bundle.getString("SecValue");
Log.i("VertygoEclypse - TaskFragment-onCreate", i);
counter=Integer.parseInt(i);
Log.i("VertygoEclypse - TaskFragment - onCreate", String.valueOf(counter).toString());
}
這樣說,這個代碼單獨工作作爲一個獨立的和作品,並給出了預期的效果。問題是,當我將它與我的應用程序配合使用時,似乎雖然值移動到片段,但我無法啓動Asynctask。以下是我的代碼到目前爲止。
這是TaskFragment.class package com.vertygoeclypse.multitimer;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.Fragment;
import android.util.Log;
public class TaskFragment extends Fragment {
private static final String TAG = TaskFragment.class.getSimpleName();
String i;
static int counter, validcounter;
Bundle bundle;
static interface TaskCallbacks {
public void onPreExecute();
public void onProgressUpdate(int timer);
public void onCancelled();
public void onPostExecute();
}
private TaskCallbacks mCallbacks;
private DummyTask mTask;
private boolean mRunning;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (!(activity instanceof TaskCallbacks)) {
throw new IllegalStateException("Activity must implement the TaskCallbacks interface.");
}
mCallbacks = (TaskCallbacks) activity;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
bundle=getArguments();
i = bundle.getString("SecValue");
Log.i("VertygoEclypse - TaskFragment-onCreate", i);
counter=Integer.parseInt(i);
Log.i("VertygoEclypse - TaskFragment - onCreate", String.valueOf(counter).toString());
}
@Override
public void onDestroy() {
super.onDestroy();
cancel();
}
public void start() {
if (!mRunning) {
Log.i("VertygoEclypse - TaskFragment - start", String.valueOf(counter).toString());
mTask = new DummyTask();
validcounter = counter;
Log.i("VertygoEclypse - TaskFragment - validcounter", String.valueOf(validcounter).toString());
mTask.execute();
mRunning = true;
} else{
mTask.cancel(true);
}
}
public void cancel() {
if (mRunning) {
mTask.cancel(true);
mTask = null;
mRunning = false;
}
}
public boolean isRunning() {
return mRunning;
}
private class DummyTask extends AsyncTask<Void, Integer, Void> {
@Override
protected void onPreExecute() {
mCallbacks.onPreExecute();
mRunning = true;
Log.i("Vertygo Eclypse - AsyncTask - onPreExecute", i);
}
@Override
protected Void doInBackground(Void... ignore) {
Log.i("Vertygo Eclypse - AsyncTask - onPreExecute", String.valueOf(validcounter).toString());
do {
publishProgress(validcounter);
SystemClock.sleep(1000);
validcounter=validcounter-1;
if(isCancelled()){
mTask.cancel(true);
break;
}
} while (validcounter>0);
return null;
}
@Override
protected void onProgressUpdate(Integer... timer) {
mCallbacks.onProgressUpdate(timer[0]);
}
@Override
protected void onCancelled() {
mCallbacks.onCancelled();
mRunning = false;
}
@Override
protected void onPostExecute(Void ignore) {
mCallbacks.onPostExecute();
mRunning = false;
}
}
}
在MainActivity是有點長,所以我希望沒有人會不高興,但我認爲,如果沒有看到代碼,一個正確的評估無法進行。
package com.vertygoeclypse.multitimer;
//--------------------------------------------------------------------------------------------------
import android.app.Dialog;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Vibrator;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.NumberPicker;
import android.widget.Spinner;
import android.widget.TextView;
import com.vertygoeclypse.multitimer.AddDialog.onSubmitListener;
import com.vertygoeclypse.multitimer.UpdateDialog.onSubmitUpdateListener;
import java.io.File;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static android.widget.AdapterView.OnItemSelectedListener;
//--------------------------------------------------------------------------------------------------
public class MainActivity extends FragmentActivity implements NumberPicker.OnValueChangeListener, OnClickListener, OnItemSelectedListener, onSubmitListener, onSubmitUpdateListener, TaskFragment.TaskCallbacks {
//--------------------------------------------------------------------------------------------------
Button abbtn, exbtn, starest, mgextbtn;
TextView timeRemaining;
Dialog mgcusd;
Typeface tf;
Spinner s;
Vibrator v;
protected CountDownTimer timerCountDownTimer;
Handler timerHandler = new Handler();
public boolean timerHasStarted = false;
protected int startTime=0;
protected int val1, val2, val3, val4, temp1, upposval, validcounter;
protected String tagval1, temp2, uptagval, uptimeval;
boolean savechkbx=true;
File mydb ;
public static Context PACKAGE_NAME;
private static final String TIME_COUNT = "time_count";
private TaskFragment mTaskFragment;
//--------------------------------------------------------------------------------------------------
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//--------------------------------------------------------------------------------------------------
PACKAGE_NAME = getApplicationContext();
TimerDataBaseHandler db = new TimerDataBaseHandler(getApplicationContext());
mydb = new File("/data/data/com.vertygoeclypse.multitimer/databases/TimerManager");
if(mydb.exists()){
} else {
db.addTimer(new TimerClass("Lipton", "180"));
}
//--------------------------------------------------------------------------------------------------
abbtn = (Button) findViewById(R.id.aboutbtn);
exbtn = (Button) findViewById(R.id.exitbtn);
starest = (Button) findViewById(R.id.startresetbtn);
timeRemaining = (TextView) findViewById(R.id.timeremainingview);
s = (Spinner)findViewById(R.id.timerspinner);
tf = Typeface.createFromAsset(getAssets(),"digital7.ttf");
v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
//--------------------------------------------------------------------------------------------------
abbtn.setOnClickListener(this);
exbtn.setOnClickListener(this);
starest.setOnClickListener(this);
s.setOnItemSelectedListener(this);
//--------------------------------------------------------------------------------------------------
if(startTime==0){
starest.setEnabled(false);
}else if(startTime>0){
starest.setEnabled(true);
starest.setTextColor(getResources().getColor(android.R.color.primary_text_light));
}
LoadSpinnerData();
if (savedInstanceState != null) {
timeRemaining.setTypeface(tf);
timeRemaining.setText(savedInstanceState.getString(TIME_COUNT));
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(TIME_COUNT, timeRemaining.getText().toString());
}
//--------------------------------------------------------------------------------------------------
public void LoadSpinnerData(){
TimerDataBaseHandler tdb = new TimerDataBaseHandler(getApplicationContext());
List<String> timerlabels = tdb.fetchAllTimers();
ArrayAdapter<String> dataAdapter;
dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, timerlabels);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s.setAdapter(dataAdapter);
}
public void mgLoadSpinnerData(){
TimerDataBaseHandler updb = new TimerDataBaseHandler(getApplicationContext());
List<String> updatetimers = updb.fetchAllTimers();
ArrayAdapter<String> dataAdapter;
dataAdapter = new ArrayAdapter<String>(this, R.layout.customer_colored_spinner_item, updatetimers);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
UpdateDialog.mgs.setAdapter(dataAdapter);
}
//--------------------------------------------------------------------------------------------------
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {}
//--------------------------------------------------------------------------------------------------
public static String getDurationBreakdown(long secondstobreak) {
if(secondstobreak < 0)
{
throw new IllegalArgumentException("Duration must be greater than zero!");
}
long hours = TimeUnit.MILLISECONDS.toHours(secondstobreak);
secondstobreak-=TimeUnit.HOURS.toMillis(hours);
long minutes = TimeUnit.MILLISECONDS.toMinutes(secondstobreak);
secondstobreak-=TimeUnit.MINUTES.toMillis(minutes);
long seconds = TimeUnit.MILLISECONDS.toSeconds(secondstobreak);
secondstobreak-=TimeUnit.SECONDS.toMillis(seconds);
StringBuilder sb = new StringBuilder(64);
if(hours<10){
sb.append("0"+hours);
}else {
sb.append(hours);
}
sb.append(" : ");
if(minutes<10){
sb.append("0"+minutes);
}else{
sb.append(minutes);
}
sb.append(" : ");
if(seconds<10){
sb.append("0"+seconds);
} else {
sb.append(seconds);
}
sb.append(" remaining");
return (sb.toString());
}
//--------------------------------------------------------------------------------------------------
public void setTimer(int minutes) {
if(timerHasStarted)
return;
startTime = minutes;
if(startTime < 1)
startTime = 1;
long val6 = (long)startTime*1000;
String ststring = getDurationBreakdown(val6);
timeRemaining.setText(ststring);
timeRemaining.setTypeface(tf);
}
//--------------------------------------------------------------------------------------------------
public void onClick(View v) {
if(v==abbtn){
aboutFragDialog();
}else if(v==exbtn){
finish();
}else if(v==starest){
if(mTaskFragment.isRunning()){
mTaskFragment.cancel();
} else {
mTaskFragment.start();
}if(v==mgextbtn){
mgcusd.dismiss();
}
}
}
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
public void aboutFragDialog(){
AboutDialog abtdialog = new AboutDialog();
abtdialog.show(getFragmentManager(),"");
}
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
public void addFragDialog(){
AddDialog dialog = new AddDialog();
dialog.minListener = MainActivity.this;
dialog.secListener = MainActivity.this;
dialog.tagListener = MainActivity.this;
dialog.chkbxListener = MainActivity.this;
dialog.show(getFragmentManager(),"");
}
//--------------------------------------------------------------------------------------------------
public void workOutResults(){
val3 = (val1*60)*1000;
val4 = val2*1000;
setTimer((val3+val4)/1000);
temp1 = startTime;
temp2 = String.valueOf(temp1);
starest.setEnabled(true);
if(tagval1.isEmpty()){
savechkbx=false;
}
if(savechkbx){
TimerDataBaseHandler tdb = new TimerDataBaseHandler(getApplicationContext());
tdb.addTimer(new TimerClass(tagval1, temp2));
}
LoadSpinnerData();
}
//--------------------------------------------------------------------------------------------------
public void updateFragDialog(){
TimerDataBaseHandler db = new TimerDataBaseHandler(getApplicationContext());
UpdateDialog updialog = new UpdateDialog();
updialog.uptgListener = MainActivity.this;
updialog.uptimListener = MainActivity.this;
updialog.upposListener = MainActivity.this;
updialog.show(getFragmentManager(),"");
}
//--------------------------------------------------------------------------------------------------
public void updateTimerresults(){
TimerDataBaseHandler mgdb = new TimerDataBaseHandler(getApplicationContext());
SQLiteDatabase mgdb1 = mgdb.getReadableDatabase();
if(mgdb1!=null){
Cursor mgc = mgdb1.rawQuery("SELECT * FROM timers where _id = "+ upposval, null);
if(mgc.moveToFirst()){
mgdb.updateTimer(new TimerClass(upposval, uptagval, uptimeval));
}
}
mgLoadSpinnerData();
}
//--------------------------------------------------------------------------------------------------
public void deleteaTimer(){
TimerDataBaseHandler deldb = new TimerDataBaseHandler(getApplicationContext());
SQLiteDatabase deldb2 = deldb.getReadableDatabase();
int tagposition1 = s.getSelectedItemPosition()+1;
String tagposval = String.valueOf(tagposition1);
if (deldb2 != null) {
Cursor cccc = deldb2.rawQuery("SELECT * FROM timers where _id = " + tagposval, null);
if(cccc.moveToFirst()){
int val0 = cccc.getInt(0);
String val1= cccc.getString(1);
String val2 = cccc.getString(2);
deldb.deleteTimer(new TimerClass(val0, val1, val2));
}
}
LoadSpinnerData();
}
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long l) {
switch(parent.getId()){
case R.id.timerspinner:
TimerDataBaseHandler isdb = new TimerDataBaseHandler(getApplicationContext());
SQLiteDatabase dbsec = isdb.getReadableDatabase();
int tagposition = s.getSelectedItemPosition()+1;
isdb.getReadableDatabase();
Cursor cc = dbsec.rawQuery("SELECT * FROM timers WHERE _id = "+tagposition, null);
if(cc.moveToFirst()){
setTimer(Integer.parseInt(cc.getString(2)));
starest.setEnabled(true);
replaceFrag();
}
}
}
//--------------------------------------------------------------------------------------------------
@Override
public void onNothingSelected(AdapterView<?> adapterView) { }
//--------------------------------------------------------------------------------------------------
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
//--------------------------------------------------------------------------------------------------
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_new) {
addFragDialog();
return true;
}else if (id == R.id.action_discard) {
deleteaTimer();
return true;
}else if (id == R.id.action_edit) {
updateFragDialog();
return true;
}
return super.onOptionsItemSelected(item);
}
//--------------------------------------------------------------------------------------------------
public void setOSMinListener(String arg){
val1 = Integer.parseInt(arg);
}
public void setOSSecListener(String arg){
val2 = Integer.parseInt(arg);
}
public void setOSTagListener(String arg){
tagval1 = arg;
}
public void setOSCkbListener(String arg){
savechkbx = Boolean.parseBoolean(arg);
}
public void updateOStagListener(String arg){
uptagval = arg;
}
public void updateOSTimeListener(String arg) {
uptimeval = arg;
}
public void updateOSPosListener(String arg){
upposval = Integer.parseInt(arg);
}
public void replaceFrag(){
Bundle bundle = new Bundle();
String tester2 = String.valueOf(startTime).toString();
Log.i("VertygoEclypse - replaceFrag - Value for counter ", tester2);
if(tester2.matches("")){
bundle.putString("SecValue", "15");
} else {
bundle.putString("SecValue", tester2);
}
FragmentManager rfm = getSupportFragmentManager();
if(mTaskFragment == null){
TaskFragment mTaskFragment = new TaskFragment();
mTaskFragment.setArguments(bundle);
rfm.beginTransaction().add(mTaskFragment, "task").commit();
} else {
TaskFragment mTaskFragment = new TaskFragment();
mTaskFragment = (TaskFragment) rfm.findFragmentByTag("task");
mTaskFragment.setArguments(bundle);
rfm.beginTransaction().add(mTaskFragment, "task").commit();
}
}
public void initialfrag(){
Log.i("VertygoEclypse - InitialFrag ","Called");
Bundle bundl = new Bundle();
String tester = timeRemaining.getText().toString();
if(tester.matches("")){
bundl.putString("SecValue", "15");
} else{
bundl.putString("SecValue", String.valueOf(startTime).toString());
}
FragmentManager fm = getSupportFragmentManager();
TaskFragment mTaskFragment = new TaskFragment();
mTaskFragment = (TaskFragment) fm.findFragmentByTag("task");
if (mTaskFragment == null) {
mTaskFragment = new TaskFragment();
mTaskFragment.setArguments(bundl);
fm.beginTransaction().add(mTaskFragment, "task").commit();
}
}
@Override
public void onPreExecute() {
starest.setText("cancel");
}
@Override
public void onProgressUpdate(int timer) {
setTimer(timer);
}
@Override
public void onCancelled() {
starest.setText("Start");
timeRemaining.setTypeface(tf);
timeRemaining.setText("0 seconds");
mTaskFragment.cancel();
replaceFrag();
}
@Override
public void onPostExecute() {
starest.setText("Start");
timeRemaining.setTypeface(tf);
timeRemaining.setText("Completed");
mTaskFragment.cancel();
replaceFrag();
}
}
任何幫助,在此,將不勝感激。
問候
cchinchoy