我有一个奇怪的问题&我希望有人可以对此有所了解:
我正在构建一个需要建立WebRTC视频会议的基本Android应用程序。保持插座/会议/视频的方向变化。我创建了一个单例以维持连接&所有工作都很好,除了...在方向改变后,主要活动不正确地读取我的布尔值。
流程基本上是: 片段状态布尔值保存到onDestroyView()中的单例 在onCreateView()
中从单例加载的片段状态布尔值片段中的值是正确的,但是当我尝试从主要活动中读取它们时,它们总是“假”。这是为什么?
另外,当我将它们作为参数传递时,它们是正确的。这是为什么?
(对于这两个问题,请参阅主要活动中的communicatorReady())
主要活动:
public class MainActivity extends Activity implements Communicator.OnEventListener{
private Communicator communicator = null;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main); // Point to layout/main.xml
// Add fragment to app
communicator = new Communicator();
if(savedInstanceState == null){
getFragmentManager()
.beginTransaction()
.add(R.id.alContainer, communicator)
.commit();
}
}
// Event listener
public void communicatorReady(boolean communicatorReady, boolean communicatorConnected, boolean userConnected){
// Also tried with a communicator.getCommunicatorReady() func, same incorrect result
Log.i(TAG, "communicator.communicatorReady " + (communicatorReady ? "true" : "false")); // Read from object, always false
Log.i(TAG, "communicatorConnected " + (communicatorConnected ? "true" : "false")); // Passed as parameter, correct value
}
}
片段:
public class Communicator extends Fragment{
// Communicator stuff
private WebView webComm = null;
private ServiceInfoEvent servInfo = null;
public boolean communicatorReady = false;
public boolean communicatorConnected = false;
public boolean userConnected = false;
// WebRTC stuff
private LocalMedia localMedia = null;
private Conference conference = null;
public CommunicatorEngine communicatorEngine = null;
// Event messages
OnEventListener eventListener;
public interface OnEventListener{
public void communicatorReady(boolean communicatorReady, boolean communicatorConnected, boolean userConnected);
}
@Override
public void onAttach(Activity activity){
super.onAttach(activity);
// Check event listener interface is implemented
try{
eventListener = (OnEventListener) activity;
}
catch(ClassCastException ex){
throw new ClassCastException(activity.toString() + " must implement OnEventListener");
}
}
// Setup the view & comms on fragment creation
public View onCreateView(LayoutInflater inflater, ViewGroup parentViewGroup, Bundle savedInstanceState){
View rootView = inflater.inflate(R.layout.alview, parentViewGroup, false);
communicatorEngine = CommunicatorEngine.getInstance(getActivity());
webComm = communicatorEngine.getWebComm();
if(!communicatorEngine.isWebCommInitialised()){
// Comm webview not initialised, do the initial setup
RelativeLayout.LayoutParams flp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
webComm.setLayoutParams(flp);
webComm.getSettings().setJavaScriptEnabled(true);
webComm.addJavascriptInterface(new ALCTranslator(getActivity()), "appJSInterface");
webComm.loadUrl("file:///android_asset/communicator.html");
webComm.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
webComm.setBackgroundColor(Color.TRANSPARENT);
communicatorEngine.setWebCommInitialised(true);
}
else{
// Webview stuff has already run, restore previously saved items
conference = communicatorEngine.getConference();
String peerID = communicatorEngine.getConferencePeerId();
communicatorReady = communicatorEngine.isCommunicatorReady();
communicatorConnected = communicatorEngine.isCommunicatorConnected();
userConnected = communicatorEngine.isUserConnected();
// Add remote video to our view if there is an active conference
if(conference != null && peerID != null){
try{
RelativeLayout incomingStreamContainer = (RelativeLayout) rootView.findViewById(R.id.contIncomingStream);
View remoteVideoControl = (View) LinkExtensions.getRemoteVideoControl(conference.getLink(peerID));
localMedia = new LocalMedia(this);
localMedia.getLayoutManager().addRemoteVideoControl(peerID, remoteVideoControl);
}
catch (Exception e){
e.printStackTrace();
}
}
// Inform the caller that the communicator is ready
eventListener.communicatorReady(communicatorReady, communicatorConnected, userConnected);
}
// Add the webview to the current view
RelativeLayout contCommunicator = (RelativeLayout) rootView.findViewById(R.id.contCommunicator);
contCommunicator.addView(webComm);
return rootView;
}
public void onDestroyView(){
RelativeLayout container = (RelativeLayout) getView().findViewById(R.id.contCommunicator);
container.removeView(webComm);
// Save connection state info
communicatorEngine.setCommunicatorReady(communicatorReady);
communicatorEngine.setCommunicatorConnected(communicatorConnected);
communicatorEngine.setUserConnected(userConnected);
super.onDestroyView();
}
}
的Singleton:
public final class CommunicatorEngine{
private static CommunicatorEngine instance = null;
// Communicator stuff
private WebView webALC = null;
private boolean webALCInitialised = false;
private boolean communicatorReady = false;
private boolean communicatorConnected = false;
private boolean userConnected = false;
private Conference conference = null;
private String conferencePeerId = null;
private CommunicatorEngine(Context context){
// Create communicator webview
webALC = new WebView(context);
webALCInitialised = false;
}
public static synchronized CommunicatorEngine getInstance(Context context){
if(instance == null){
// Use app context to prevent memory leaks
instance = new CommunicatorEngine(context.getApplicationContext());
}
return instance;
}
public WebView getWebALC() {return webALC;}
public boolean isWebALCInitialised() {return webALCInitialised;}
public void setWebALCInitialised(boolean isInitialised) {webALCInitialised = isInitialised;}
public boolean isCommunicatorReady(){return communicatorReady;}
public void setCommunicatorReady(boolean isReady){communicatorReady = isReady;}
public boolean isCommunicatorConnected(){return communicatorConnected;}
public void setCommunicatorConnected(boolean isConnected){communicatorConnected = isConnected;}
public boolean isUserConnected(){return userConnected;}
public void setUserConnected(boolean isConnected){userConnected = isConnected;}
public Conference getConference() {return conference;}
public void setConference(Conference conferenceToSave) {conference = conferenceToSave;}
public String getConferencePeerId() {return conferencePeerId;}
public void setConferencePeerId(String peerIdToSave) {conferencePeerId = peerIdToSave;}
}
添加日志消息会产生以下结果:
Fragment﹕ ********* onDestroyView() *********
Fragment﹕ Saved communicatorReady true
Fragment﹕ Saved communicatorConnected true
Fragment﹕ Saved userConnected false
Fragment﹕ ********* onCreateView() *********
Fragment﹕ Loaded communicatorReady true
Fragment﹕ Loaded communicatorConnected true
Fragment﹕ Loaded userConnected false
Activity﹕ communicatorReady Event
Activity﹕ *******************
Activity﹕ Passed as parameter: communicatorReady true
Activity﹕ Passed as parameter: communicatorConnected true
Activity﹕ Passed as parameter: userConnected false
Activity﹕ ********************************
Activity﹕ communicator.communicatorReady false
Activity﹕ communicator.communicatorConnected false
Activity﹕ communicator.userConnected false
如果我将通信器设置为静态,问题就会消失:
private static Communicator communicator;
我猜这是一个被查询错误对象的问题。