我有两个片段。 在他们之间的交易我正在取代他们。 在第二个片段,我有一个Timer更新TextView。 这是我需要的流程。
我的问题是,当我回到第二个Fragment并且Timer正在运行时,TextView不再更新。
这是我的代码:
MainActivity:
public class MainActivity extends AppCompatActivity{
private FragmentManager fragmentManager;
private FragmentTransaction fragmentTransaction;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setFragmentTransaction(null);
}
/**
* A fragment transaction Method
*
* @param fragment the fragment we want to display
*/
public void setFragmentTransaction(Fragment fragment) {
fragmentManager = getFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
//replacing fragments new Fragments
if (fragment != null ) {
fragmentTransaction.replace(R.id.container, fragment);
} else if(fragment == null && (fragmentManager.getBackStackEntryCount() == 0)) { // starting with main Fragment
fragmentTransaction.add(R.id.container, new MainFragment());
}
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
}
}
主要片段:
public class MainFragment extends Fragment {
private Context context;
private View view;
private Button button;
@Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_main, container, false);
button = (Button) view.findViewById(R.id.mainBTN);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
((MainActivity)context).setFragmentTransaction(new TimerFragmnet());
}
});
return view;
}
}
计时器片段:
public class TimerFragmnet extends Fragment {
private Context context;
private TextView timerTextView;
private Button startBTN, backBTN;
private View view;
private Timer timer;
private int timerSec;
@Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_timer, container, false);
timerTextView = (TextView) view.findViewById(R.id.timerTextView);
startBTN = (Button) view.findViewById(R.id.startBTN);
backBTN = (Button) view.findViewById(R.id.backBTN);
startBTN.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startTimer(180);
}
});
backBTN.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
((MainActivity) context).setFragmentTransaction(new MainFragment());
}
});
return view;
}
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.i("Timer", msg.toString());
timerTextView.setText(createDateFormat((int) msg.obj));
}
};
private void startTimer(final int seconds) {
timerSec = seconds;
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
Message message = Message.obtain();
message.obj = timerSec;
message.setTarget(mHandler);
mHandler.sendMessage(message);
timerSec--;
}
}, 100, 1000);
}
/**
* Setting the timer format
*
* @param seconds
* @return
*/
public String createDateFormat(int seconds) {
return String.format("%02d:%02d", (seconds % 3600) / 60, (seconds % 60));
}
}
答案 0 :(得分:3)
我最终做到了: 我创建了一个新的Class,它使得所有的Timer处理和我的Fragment实现了他的回调: 对于任何情况,我都会在这里使用代码:
<强> MainActivity:强>
public class MainActivity extends AppCompatActivity {
private FragmentManager fragmentManager;
private FragmentTransaction fragmentTransaction;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setFragmentTransaction(null);
}
/**
* A fragment transaction Method
*
* @param fragment the fragment we want to display
*/
public void setFragmentTransaction(Fragment fragment) {
fragmentManager = getFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
//replacing fragments new Fragments
if (fragment != null ) {
fragmentTransaction.replace(R.id.container, fragment);
} else if(fragment == null && (fragmentManager.getBackStackEntryCount() == 0)) { // starting with main Fragment
fragmentTransaction.add(R.id.container, new MainFragment());
}
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
}
}
<强> MainFragment:强>
public class MainFragment extends Fragment {
private Context context;
private View view;
private Button button;
@Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_main, container, false);
button = (Button) view.findViewById(R.id.mainBTN);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
((MainActivity)context).setFragmentTransaction(new TimerFragment());
}
});
return view;
}
}
<强> TimerFragment:强>
public class TimerFragment extends Fragment implements MyTimer.TimerRuning {
private Context context;
private TextView timerUpTextView, timerDownTextView;
private Button startBTN, backBTN, stopTimerBTN;
private View view;
@Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
MyTimer.getInstance().setTimerRuningListener(this);
view = inflater.inflate(R.layout.fragment_timer, container, false);
timerUpTextView = (TextView) view.findViewById(R.id.timerUpTextView);
timerDownTextView = (TextView) view.findViewById(R.id.timerDownTextView);
startBTN = (Button) view.findViewById(R.id.startBTN);
backBTN = (Button) view.findViewById(R.id.backBTN);
stopTimerBTN = (Button) view.findViewById(R.id.stopTimerBTN);
startBTN.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyTimer.getInstance().startTimer(180);
}
});
stopTimerBTN.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyTimer.getInstance().stopTimer();
}
});
backBTN.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
((MainActivity) context).setFragmentTransaction(new MainFragment());
}
});
return view;
}
@Override
public void onTimerChange(String remainSec, String startSec) {
timerUpTextView.setText(startSec);
timerDownTextView.setText(remainSec);
}
@Override
public void onTimerStopped(String remainSec, String startSec) {
timerUpTextView.setText(startSec);
timerDownTextView.setText(remainSec);
}
}
MyTimer - Class
public class MyTimer {
private Timer timer;
private MyTimer.TimerRuning timerRuningListener;
private int remainingSec, startSec;
public boolean isRunning;
private static final String TAG = "MyTimer";
private static final MyTimer ourInstance = new MyTimer();
public static MyTimer getInstance() {
return ourInstance;
}
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
int[] timeArr = (int[]) msg.obj;
if (timeArr[0] == 0) {
MyTimer.this.stopTimer();
if(timerRuningListener != null) {
timerRuningListener.onTimerStopped(createDateFormat(0), createDateFormat(0));
}
} else {
if(timerRuningListener != null) {
timerRuningListener.onTimerChange(createDateFormat(timeArr[0]), createDateFormat(timeArr[1]));
}
}
}
};
public void startTimer(final int seconds) {
startSec = 0;
remainingSec = seconds;
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
Log.i(TAG, "Timer running......");
isRunning = true;
Message message = Message.obtain();
int[] counters = new int[2];
counters[0] = remainingSec;
counters[1] = startSec;
message.obj = counters;
message.setTarget(mHandler);
mHandler.sendMessage(message);
remainingSec--;
startSec++;
}
}, 100, 1000);
}
/**
* Setting the timer format
*
* @param seconds
* @return
*/
public String createDateFormat(int seconds) {
return String.format("%02d:%02d", (seconds % 3600) / 60, (seconds % 60));
}
public void setTimerRuningListener(MyTimer.TimerRuning timerRuningListener) {
this.timerRuningListener = timerRuningListener;
}
public interface TimerRuning {
void onTimerChange(String remainSec, String startSec);
void onTimerStopped(String remainSec, String startSec);
}
public void stopTimer() {
if (timer != null) {
timerRuningListener.onTimerStopped(createDateFormat(0), createDateFormat(0));
isRunning = false;
timer.cancel();
}
}
}
答案 1 :(得分:0)
当我回到第二片段并且计时器正在运行时,你的意思是什么?当你回到你的第一个片段时,第二个片段会被破坏,计时器也会被破坏。当你“回到”第二个片段时,你正在创建一个新实例,它将有一个未运行的新计时器。
我建议您使用Service
。您可以在那里启动计时器并每秒发送一次广播来更新您的UI。当您的第二个片段开始时,您注册一个BroadcastReceiver
将获得这些更新。当该片段停止时,您可以取消注册BroadcastReceiver
。